Automatically reset forms after action finishes - #28804

Merged
acdlite merged 1 commit into
react:mainfrom
acdlite:automatically-reset-forms
Apr 10, 2024
Merged

Automatically reset forms after action finishes#28804
acdlite merged 1 commit into
react:mainfrom
acdlite:automatically-reset-forms

Conversation

@acdlite

Copy link
Copy Markdown
Collaborator

This updates the behavior of form actions to automatically reset the form's uncontrolled inputs after the action finishes.

This is a frequent feature request for people using actions and it aligns the behavior of client-side form submissions more closely with MPA form submissions.

It has no impact on controlled form inputs. It's the same as if you called form.reset() manually, except React handles the timing of when the reset happens, which is tricky/impossible to get exactly right in userspace.

The reset shouldn't happen until the UI has updated with the result of the action. So, resetting inside the action is too early.

Resetting in useEffect is better, but it's later than ideal because any effects that run before it will observe the state of the form before it's been reset.

It needs to happen in the mutation phase of the transition. More specifically, after all the DOM mutations caused by the transition have been applied. That way the defaultValue of the inputs are updated before the values are reset. The idea is that the defaultValue represents the current, canonical value sent by the server.

Note: this change has no effect on form submissions that aren't triggered by an action.

@facebook-github-botfacebook-github-bot added CLA Signed React Core Team Opened by a member of the React Core Team labels Apr 10, 2024
@react-sizebot

react-sizebot commented Apr 10, 2024

Copy link
Copy Markdown

Comparing: ed3c65c...562f9c9

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name+/-BaseCurrent+/- gzipBase gzipCurrent gzip
oss-stable/react-dom/cjs/react-dom.production.min.js+0.27%168.12 kB168.57 kB+0.24%52.72 kB52.85 kB
oss-experimental/react-dom/cjs/react-dom.production.min.js+0.26%169.92 kB170.37 kB+0.20%53.26 kB53.37 kB
facebook-www/ReactDOM-prod.classic.js+0.22%589.57 kB590.89 kB+0.22%103.80 kB104.03 kB
facebook-www/ReactDOM-prod.modern.js+0.23%565.41 kB566.73 kB+0.23%99.93 kB100.16 kB
test_utils/ReactAllWarnings.jsDeleted64.24 kB0.00 kBDeleted16.03 kB0.00 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name+/-BaseCurrent+/- gzipBase gzipCurrent gzip
oss-stable-semver/react-reconciler/cjs/react-reconciler.production.js+0.49%665.84 kB669.08 kB+0.51%146.23 kB146.97 kB
oss-stable/react-reconciler/cjs/react-reconciler.production.js+0.49%665.86 kB669.11 kB+0.51%146.26 kB147.01 kB
oss-experimental/react-reconciler/cjs/react-reconciler.production.js+0.48%672.88 kB676.12 kB+0.53%147.79 kB148.57 kB
oss-stable-semver/react-reconciler/cjs/react-reconciler.development.js+0.48%908.86 kB913.24 kB+0.53%195.30 kB196.34 kB
oss-stable/react-reconciler/cjs/react-reconciler.development.js+0.48%908.89 kB913.27 kB+0.53%195.33 kB196.37 kB
oss-experimental/react-reconciler/cjs/react-reconciler.development.js+0.48%918.20 kB922.58 kB+0.53%197.14 kB198.19 kB
oss-stable-semver/react-reconciler/cjs/react-reconciler.profiling.js+0.46%705.86 kB709.10 kB+0.50%153.52 kB154.29 kB
oss-stable/react-reconciler/cjs/react-reconciler.profiling.js+0.46%705.89 kB709.13 kB+0.50%153.55 kB154.31 kB
oss-experimental/react-reconciler/cjs/react-reconciler.profiling.js+0.46%712.90 kB716.14 kB+0.49%155.11 kB155.88 kB
oss-stable-semver/react-reconciler/cjs/react-reconciler.production.min.js+0.43%108.56 kB109.03 kB+0.39%33.85 kB33.98 kB
oss-stable/react-reconciler/cjs/react-reconciler.production.min.js+0.43%108.59 kB109.06 kB+0.39%33.87 kB34.00 kB
oss-experimental/react-reconciler/cjs/react-reconciler.production.min.js+0.42%110.35 kB110.82 kB+0.37%34.47 kB34.60 kB
oss-stable-semver/react-reconciler/cjs/react-reconciler.profiling.min.js+0.40%117.42 kB117.89 kB+0.32%36.09 kB36.21 kB
oss-stable/react-reconciler/cjs/react-reconciler.profiling.min.js+0.40%117.45 kB117.92 kB+0.33%36.11 kB36.23 kB
oss-experimental/react-reconciler/cjs/react-reconciler.profiling.min.js+0.39%119.21 kB119.67 kB+0.41%36.65 kB36.80 kB
oss-stable-semver/react-dom/cjs/react-dom.production.js+0.35%919.85 kB923.06 kB+0.37%206.89 kB207.65 kB
oss-stable/react-dom/cjs/react-dom.production.js+0.35%919.87 kB923.08 kB+0.37%206.92 kB207.68 kB
oss-experimental/react-dom/cjs/react-dom.production.js+0.35%926.94 kB930.15 kB+0.37%208.43 kB209.20 kB
oss-experimental/react-dom/cjs/react-dom-unstable_testing.production.js+0.34%945.18 kB948.39 kB+0.36%212.95 kB213.71 kB
oss-stable-semver/react-dom/cjs/react-dom.development.js+0.34%1,293.34 kB1,297.68 kB+0.37%286.49 kB287.55 kB
oss-stable/react-dom/cjs/react-dom.development.js+0.34%1,293.36 kB1,297.71 kB+0.37%286.52 kB287.58 kB
oss-stable-semver/react-dom/umd/react-dom.development.js+0.34%1,356.09 kB1,360.63 kB+0.38%289.40 kB290.49 kB
oss-stable/react-dom/umd/react-dom.development.js+0.34%1,356.12 kB1,360.66 kB+0.38%289.43 kB290.52 kB
oss-stable-semver/react-dom/cjs/react-dom.profiling.js+0.33%960.46 kB963.67 kB+0.35%214.16 kB214.92 kB
oss-stable/react-dom/cjs/react-dom.profiling.js+0.33%960.48 kB963.69 kB+0.35%214.19 kB214.95 kB
oss-experimental/react-dom/cjs/react-dom.development.js+0.33%1,302.73 kB1,307.08 kB+0.37%288.32 kB289.39 kB
oss-experimental/react-dom/umd/react-dom.development.js+0.33%1,365.97 kB1,370.51 kB+0.36%291.21 kB292.26 kB
oss-experimental/react-dom/cjs/react-dom.profiling.js+0.33%967.55 kB970.76 kB+0.35%215.71 kB216.46 kB
oss-experimental/react-dom/cjs/react-dom-unstable_testing.development.js+0.33%1,321.15 kB1,325.50 kB+0.37%292.77 kB293.84 kB
facebook-www/ReactDOM-dev.modern.js+0.30%1,621.20 kB1,626.01 kB+0.34%322.53 kB323.63 kB
facebook-www/ReactDOMTesting-dev.modern.js+0.29%1,644.60 kB1,649.41 kB+0.34%327.14 kB328.26 kB
facebook-www/ReactDOM-dev.classic.js+0.29%1,673.24 kB1,678.05 kB+0.34%331.38 kB332.50 kB
facebook-www/ReactDOMTesting-dev.classic.js+0.28%1,697.92 kB1,702.73 kB+0.33%336.19 kB337.31 kB
oss-stable-semver/react-dom/umd/react-dom.production.min.js+0.27%167.79 kB168.24 kB+0.28%53.04 kB53.19 kB
oss-stable/react-dom/umd/react-dom.production.min.js+0.27%167.87 kB168.32 kB+0.28%53.07 kB53.22 kB
oss-stable-semver/react-dom/cjs/react-dom.production.min.js+0.27%168.04 kB168.49 kB+0.24%52.69 kB52.82 kB
oss-stable/react-dom/cjs/react-dom.production.min.js+0.27%168.12 kB168.57 kB+0.24%52.72 kB52.85 kB
oss-experimental/react-dom/umd/react-dom.production.min.js+0.27%169.67 kB170.13 kB+0.25%53.70 kB53.83 kB
oss-experimental/react-dom/cjs/react-dom.production.min.js+0.26%169.92 kB170.37 kB+0.20%53.26 kB53.37 kB
oss-stable-semver/react-dom/umd/react-dom.profiling.min.js+0.25%176.63 kB177.08 kB+0.21%55.45 kB55.56 kB
oss-stable/react-dom/umd/react-dom.profiling.min.js+0.25%176.71 kB177.16 kB+0.21%55.47 kB55.59 kB
oss-experimental/react-dom/cjs/react-dom-unstable_testing.production.min.js+0.25%176.86 kB177.31 kB+0.20%55.85 kB55.97 kB
oss-stable-semver/react-dom/cjs/react-dom.profiling.min.js+0.25%177.32 kB177.77 kB+0.22%55.14 kB55.26 kB
oss-stable/react-dom/cjs/react-dom.profiling.min.js+0.25%177.40 kB177.85 kB+0.22%55.16 kB55.28 kB
oss-experimental/react-dom/umd/react-dom.profiling.min.js+0.25%178.51 kB178.96 kB+0.25%56.01 kB56.15 kB
oss-experimental/react-dom/cjs/react-dom.profiling.min.js+0.25%179.21 kB179.66 kB+0.25%55.71 kB55.85 kB
facebook-www/ReactDOM-prod.modern.js+0.23%565.41 kB566.73 kB+0.23%99.93 kB100.16 kB
facebook-www/ReactDOMTesting-prod.modern.js+0.23%581.36 kB582.67 kB+0.22%103.88 kB104.11 kB
facebook-www/ReactDOM-prod.classic.js+0.22%589.57 kB590.89 kB+0.22%103.80 kB104.03 kB
facebook-www/ReactDOM-profiling.modern.js+0.22%594.31 kB595.63 kB+0.22%104.07 kB104.29 kB
facebook-www/ReactDOMTesting-prod.classic.js+0.22%604.22 kB605.54 kB+0.21%107.51 kB107.74 kB
facebook-www/ReactDOM-profiling.classic.js+0.21%619.11 kB620.43 kB+0.22%108.10 kB108.33 kB
test_utils/ReactAllWarnings.jsDeleted64.24 kB0.00 kBDeleted16.03 kB0.00 kB

Generated by 🚫 dangerJS against 562f9c9

@acdlite
acdliteforce-pushed the automatically-reset-forms branch 2 times, most recently from 5e8fad4 to 41e6173CompareApril 10, 2024 00:38
@acdlite
acdlite marked this pull request as ready for review April 10, 2024 00:41

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should start a campaign for javascript64

@acdliteacdlite mentioned this pull request Apr 10, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right
in userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
@acdlite
acdliteforce-pushed the automatically-reset-forms branch from 41e6173 to 562f9c9CompareApril 10, 2024 04:04
const newResetState = {};
const resetStateHook: Hook = (formFiber.memoizedState.next: any);
const resetStateQueue = resetStateHook.queue;
dispatchSetState(formFiber, resetStateQueue, newResetState);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this actually have to be on the Fiber?

Can't it just be scheduled on the Root with a list of forms to reset when the root commits?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That way you don't need all the special commit phase stuff.

@acdliteacdliteApr 10, 2024

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm I'll need to think more about that, the scenario I had in mind was if the form is inside a Suspense boundary, the root could commit before the input's defaultValue had been updated. Usually this shouldn't happen because during a Transition we won't hide already visible forms, but during a popstate transition we might.

The <input form="myform"> case is interesting there, too.

@acdlite
acdlite merged commit 41950d1 into react:mainApr 10, 2024
acdlite added a commit that referenced this pull request Apr 10, 2024
Based on:
- #28804 ---
This sets adds a new ReactDOM export called requestFormReset, including
setting up the export and creating a method on the internal ReactDOM
dispatcher. It does not yet add any implementation.
Doing this in its own commit for review purposes.
The API itself will be explained in the next PR.
acdlite added a commit that referenced this pull request Apr 10, 2024
Based on:
- #28808
- #28804 ---
This adds a React DOM method called requestFormReset that schedules a
form reset to occur when the current transition completes.
Internally, it's the same method that's called automatically whenever a
form action is submitted. It only affects uncontrolled form inputs. See
#28804 for details.
The reason for the public API is so UI libraries can implement their own
action-based APIs and maintain the form-resetting behavior, something
like this:
```js
function onSubmit(event) {
// Disable default form submission behavior
event.preventDefault();
const form = event.target;
startTransition(async () => {
// Request the form to reset once the action
// has completed
requestFormReset(form);
// Call the user-provided action prop
await action(new FormData(form));
})
}
```
github-actionsBot pushed a commit that referenced this pull request Apr 10, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right in
userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
DiffTrain build for [41950d1](41950d1)
github-actionsBot pushed a commit that referenced this pull request Apr 10, 2024
Based on:
- #28804
---
This sets adds a new ReactDOM export called requestFormReset, including
setting up the export and creating a method on the internal ReactDOM
dispatcher. It does not yet add any implementation.
Doing this in its own commit for review purposes.
The API itself will be explained in the next PR.
DiffTrain build for [374b5d2](374b5d2)
github-actionsBot pushed a commit that referenced this pull request Apr 10, 2024
Based on:
- #28808
- #28804
---
This adds a React DOM method called requestFormReset that schedules a
form reset to occur when the current transition completes.
Internally, it's the same method that's called automatically whenever a
form action is submitted. It only affects uncontrolled form inputs. See
#28804 for details.
The reason for the public API is so UI libraries can implement their own
action-based APIs and maintain the form-resetting behavior, something
like this:
```js
function onSubmit(event) {
// Disable default form submission behavior
event.preventDefault();
const form = event.target;
startTransition(async () => {
// Request the form to reset once the action
// has completed
requestFormReset(form);
// Call the user-provided action prop
await action(new FormData(form));
})
}
```
DiffTrain build for [da69b6a](da69b6a)
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right in
userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
Based on:
- #28804 ---
This sets adds a new ReactDOM export called requestFormReset, including
setting up the export and creating a method on the internal ReactDOM
dispatcher. It does not yet add any implementation.
Doing this in its own commit for review purposes.
The API itself will be explained in the next PR.
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
Based on:
- #28808
- #28804 ---
This adds a React DOM method called requestFormReset that schedules a
form reset to occur when the current transition completes.
Internally, it's the same method that's called automatically whenever a
form action is submitted. It only affects uncontrolled form inputs. See
#28804 for details.
The reason for the public API is so UI libraries can implement their own
action-based APIs and maintain the form-resetting behavior, something
like this:
```js
function onSubmit(event) {
// Disable default form submission behavior
event.preventDefault();
const form = event.target;
startTransition(async () => {
// Request the form to reset once the action
// has completed
requestFormReset(form);
// Call the user-provided action prop
await action(new FormData(form));
})
}
```
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right in
userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
Based on:
- #28804 ---
This sets adds a new ReactDOM export called requestFormReset, including
setting up the export and creating a method on the internal ReactDOM
dispatcher. It does not yet add any implementation.
Doing this in its own commit for review purposes.
The API itself will be explained in the next PR.
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
Based on:
- #28808
- #28804 ---
This adds a React DOM method called requestFormReset that schedules a
form reset to occur when the current transition completes.
Internally, it's the same method that's called automatically whenever a
form action is submitted. It only affects uncontrolled form inputs. See
#28804 for details.
The reason for the public API is so UI libraries can implement their own
action-based APIs and maintain the form-resetting behavior, something
like this:
```js
function onSubmit(event) {
// Disable default form submission behavior
event.preventDefault();
const form = event.target;
startTransition(async () => {
// Request the form to reset once the action
// has completed
requestFormReset(form);
// Call the user-provided action prop
await action(new FormData(form));
})
}
```
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right in
userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
Based on:
- react#28804 ---
This sets adds a new ReactDOM export called requestFormReset, including
setting up the export and creating a method on the internal ReactDOM
dispatcher. It does not yet add any implementation.
Doing this in its own commit for review purposes.
The API itself will be explained in the next PR.
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
Based on:
- react#28808
- react#28804 ---
This adds a React DOM method called requestFormReset that schedules a
form reset to occur when the current transition completes.
Internally, it's the same method that's called automatically whenever a
form action is submitted. It only affects uncontrolled form inputs. See
react#28804 for details.
The reason for the public API is so UI libraries can implement their own
action-based APIs and maintain the form-resetting behavior, something
like this:
```js
function onSubmit(event) {
// Disable default form submission behavior
event.preventDefault();
const form = event.target;
startTransition(async () => {
// Request the form to reset once the action
// has completed
requestFormReset(form);
// Call the user-provided action prop
await action(new FormData(form));
})
}
```
bigfootjon pushed a commit that referenced this pull request Apr 18, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right in
userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
DiffTrain build for commit 41950d1.
facebook-github-bot pushed a commit to react/react-native that referenced this pull request Apr 19, 2024
Summary:
This sync includes the changes from:
- D56103750
- [TODO] A shim for SECRET_INTERNALS
This sync includes the following changes:
- **[b5e5ce8](react/react@b5e5ce8e0 )**: Update ReactNativeTypes for root options (part 2) ([#28857](react/react#28857)) //<Ricky>//
- **[da6ba53](react/react@da6ba53b1 )**: [UMD] Remove umd builds ([#28735](react/react#28735)) //<Josh Story>//
- **[0c245df](react/react@0c245df1d )**: Complete the typo fix ([#28856](react/react#28856)) //<Sebastian Silbermann>//
- **[f82051d](react/react@f82051d7a )**: console test utils fix: match entire string, not just first letter ([#28855](react/react#28855)) //<Andrew Clark>//
- **[4ca20fd](react/react@4ca20fd36 )**: Test top level fragment inside lazy semantics ([#28852](react/react#28852)) //<Sebastian Markbåge>//
- **[c0cf7c6](react/react@c0cf7c696 )**: Promote ASYNC_ITERATOR symbol to React Symbols ([#28851](react/react#28851)) //<Sebastian Markbåge>//
- **[657428a](react/react@657428a9e )**: Add ReactNativeTypes for root options ([#28850](react/react#28850)) //<Ricky>//
- **[7909d8e](react/react@7909d8eab )**: [Flight] Encode ReadableStream and AsyncIterables ([#28847](react/react#28847)) //<Sebastian Markbåge>//
- **[13eb61d](react/react@13eb61d05 )**: Move enableUseDeferredValueInitialArg to canary ([#28818](react/react#28818)) //<Andrew Clark>//
- **[8afa144](react/react@8afa144bd )**: Enable flag disableClientCache ([#28846](react/react#28846)) //<Jan Kassens>//
- **[734956a](react/react@734956ace )**: Devtools: Add support for useFormStatus ([#28413](react/react#28413)) //<Sebastian Silbermann>//
- **[17e920c](react/react@17e920c00 )**: [Flight Reply] Encode Typed Arrays and Blobs ([#28819](react/react#28819)) //<Sebastian Markbåge>//
- **[0347fcd](react/react@0347fcd00 )**: Add on(Caught|Uncaught|Recoverable) opts to RN ([#28836](react/react#28836)) //<Ricky>//
- **[c113503](react/react@c113503ad )**: Flush direct streams in Bun ([#28837](react/react#28837)) //<Kenta Iwasaki>//
- **[9defcd5](react/react@9defcd56b )**: Remove redundant props assign ([#28829](react/react#28829)) //<Sebastian Silbermann>//
- **[ed40236](react/react@ed4023603 )**: Fix mistaken "react-server" condition ([#28835](react/react#28835)) //<Sebastian Markbåge>//
- **[c8a0350](react/react@c8a035036 )**: [Fizz] hoistables should never flush before the preamble ([#28802](react/react#28802)) //<Josh Story>//
- **[4f5c812](react/react@4f5c812a3 )**: DevTools: Rely on sourcemaps to compute hook name of built-in hooks in newer versions ([#28593](react/react#28593)) //<Sebastian Silbermann>//
- **[4354159](react/react@435415962 )**: Backwards compatibility for string refs on WWW ([#28826](react/react#28826)) //<Jack Pope>//
- **[608edcc](react/react@608edcc90 )**: [tests] add `assertConsole<method>Dev` helpers ([#28732](react/react#28732)) //<Ricky>//
- **[da69b6a](react/react@da69b6af9 )**: ReactDOM.requestFormReset ([#28809](react/react#28809)) //<Andrew Clark>//
- **[374b5d2](react/react@374b5d26c )**: Scaffolding for requestFormReset API ([#28808](react/react#28808)) //<Andrew Clark>//
- **[41950d1](react/react@41950d14a )**: Automatically reset forms after action finishes ([#28804](react/react#28804)) //<Andrew Clark>//
- **[dc6a7e0](react/react@dc6a7e01e )**: [Float] Don't preload images inside `<noscript>` ([#28815](react/react#28815)) //<Josh Story>//
- **[3f947b1](react/react@3f947b1b4 )**: [tests] Assert scheduler log empty in internalAct ([#28737](react/react#28737)) //<Ricky>//
- **[bf09089](react/react@bf09089f6 )**: Remove Scheduler.log from ReactSuspenseFuzz-test ([#28812](react/react#28812)) //<Ricky>//
- **[84cb3b4](react/react@84cb3b4cb )**: Hardcode disableIEWorkarounds for www ([#28811](react/react#28811)) //<Ricky>//
- **[2243b40](react/react@2243b40ab )**: [tests] assertLog before act in useEffectEvent ([#28763](react/react#28763)) //<Ricky>//
- **[dfc64c6](react/react@dfc64c6e3 )**: [tests] assertLog before act in ReactUse ([#28762](react/react#28762)) //<Ricky>//
- **[42eff4b](react/react@42eff4bc7 )**: [tests] Fix assertions not flushed before act ([#28745](react/react#28745)) //<Ricky>//
- **[ed3c65c](react/react@ed3c65caf )**: Warn if outdated JSX transform is detected ([#28781](react/react#28781)) //<Andrew Clark>//
- **[3f9e237](react/react@3f9e237a2 )**: Fix: Suspend while recovering from hydration error ([#28800](react/react#28800)) //<Andrew Clark>//
- **[7f5d25e](react/react@7f5d25e23 )**: Fix cloneElement using string ref w no owner ([#28797](react/react#28797)) //<Joseph Savona>//
- **[bf40b02](react/react@bf40b0244 )**: [Fizz] Stop publishing external-runtime to stable channel ([#28796](react/react#28796)) //<Josh Story>//
- **[7f93cb4](react/react@7f93cb41c )**: [DOM] Infer react-server entries bundles if not explicitly configured ([#28795](react/react#28795)) //<Josh Story>//
- **[f613165](react/react@f61316535 )**: Rename SECRET INTERNALS to `__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE` ([#28789](react/react#28789)) //<Sebastian Markbåge>//
- **[9644d20](react/react@9644d206e )**: Soften useFormState warning ([#28788](react/react#28788)) //<Ricky>//
- **[c771016](react/react@c771016e1 )**: Rename The Secret Export of Server Internals ([#28786](react/react#28786)) //<Sebastian Markbåge>//
- **[d50323e](react/react@d50323eb8 )**: Flatten ReactSharedInternals ([#28783](react/react#28783)) //<Sebastian Markbåge>//
- **[f62cf8c](react/react@f62cf8c62 )**: [Float] treat `props.async` in Float consistent with the rest of react-dom ([#26760](react/react#26760)) //<Josh Story>//
- **[dfd3d5a](react/react@dfd3d5af8 )**: Add support for transition{run,start,cancel} events ([#27345](react/react#27345)) //<Hugo Sales>//
- **[1f8327f](react/react@1f8327f83 )**: [Fiber] Use real event priority for hydration scheduling ([#28765](react/react#28765)) //<Josh Story>//
- **[97c90ed](react/react@97c90ed88 )**: [DOM] Shrink ReactDOMCurrentDispatcher method names ([#28770](react/react#28770)) //<Josh Story>//
- **[9007fdc](react/react@9007fdc8f )**: [DOM] Shrink ReactDOMSharedInternals source representation ([#28771](react/react#28771)) //<Josh Story>//
- **[14f50ad](react/react@14f50ad15 )**: [Flight] Allow lazily resolving outlined models ([#28780](react/react#28780)) //<Sebastian Markbåge>//
- **[4c12339](react/react@4c12339ce )**: [DOM] move `flushSync` out of the reconciler ([#28500](react/react#28500)) //<Josh Story>//
- **[8e1462e](react/react@8e1462e8c )**: [Fiber] Move updatePriority tracking to renderers ([#28751](react/react#28751)) //<Josh Story>//
- **[0b3b8a6](react/react@0b3b8a6a3 )**: jsx: Remove unnecessary hasOwnProperty check ([#28775](react/react#28775)) //<Andrew Clark>//
- **[2acfb7b](react/react@2acfb7b60 )**: [Flight] Support FormData from Server to Client ([#28754](react/react#28754)) //<Sebastian Markbåge>//
- **[d1547de](react/react@d1547defe )**: Fast JSX: Don't clone props object ([#28768](react/react#28768)) //<Andrew Clark>//
- **[bfd8da8](react/react@bfd8da807 )**: Make class prop resolution faster ([#28766](react/react#28766)) //<Andrew Clark>//
- **[cbb6f2b](react/react@cbb6f2b54 )**: [Flight] Support Blobs from Server to Client ([#28755](react/react#28755)) //<Sebastian Markbåge>//
- **[f33a6b6](react/react@f33a6b69c )**: Track Owner for Server Components in DEV ([#28753](react/react#28753)) //<Sebastian Markbåge>//
- **[e3ebcd5](react/react@e3ebcd54b )**: Move string ref coercion to JSX runtime ([#28473](react/react#28473)) //<Andrew Clark>//
- **[fd0da3e](react/react@fd0da3eef )**: Remove _owner field from JSX elements in prod if string refs are disabled ([#28739](react/react#28739)) //<Sebastian Markbåge>//
Changelog:
[General][Changed] - React Native sync for revisions 48b4ecc...b5e5ce8
jest_e2e[run_all_tests]
bypass-github-export-checks
Reviewed By: kassens
Differential Revision: D56251607
fbshipit-source-id: e16db2fa101fc7ed1e009158c76388206beabd5f
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA SignedReact Core TeamOpened by a member of the React Core Team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@acdlite@react-sizebot@sebmarkbage@gnoff@facebook-github-bot
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Automatically reset forms after action finishes - #28804

Merged
acdlite merged 1 commit into
react:mainfrom
acdlite:automatically-reset-forms
Apr 10, 2024
Merged

Automatically reset forms after action finishes#28804
acdlite merged 1 commit into
react:mainfrom
acdlite:automatically-reset-forms

Conversation

@acdlite

Copy link
Copy Markdown
Collaborator

This updates the behavior of form actions to automatically reset the form's uncontrolled inputs after the action finishes.

This is a frequent feature request for people using actions and it aligns the behavior of client-side form submissions more closely with MPA form submissions.

It has no impact on controlled form inputs. It's the same as if you called form.reset() manually, except React handles the timing of when the reset happens, which is tricky/impossible to get exactly right in userspace.

The reset shouldn't happen until the UI has updated with the result of the action. So, resetting inside the action is too early.

Resetting in useEffect is better, but it's later than ideal because any effects that run before it will observe the state of the form before it's been reset.

It needs to happen in the mutation phase of the transition. More specifically, after all the DOM mutations caused by the transition have been applied. That way the defaultValue of the inputs are updated before the values are reset. The idea is that the defaultValue represents the current, canonical value sent by the server.

Note: this change has no effect on form submissions that aren't triggered by an action.

@facebook-github-botfacebook-github-bot added CLA Signed React Core Team Opened by a member of the React Core Team labels Apr 10, 2024
@react-sizebot

react-sizebot commented Apr 10, 2024

Copy link
Copy Markdown

Comparing: ed3c65c...562f9c9

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name+/-BaseCurrent+/- gzipBase gzipCurrent gzip
oss-stable/react-dom/cjs/react-dom.production.min.js+0.27%168.12 kB168.57 kB+0.24%52.72 kB52.85 kB
oss-experimental/react-dom/cjs/react-dom.production.min.js+0.26%169.92 kB170.37 kB+0.20%53.26 kB53.37 kB
facebook-www/ReactDOM-prod.classic.js+0.22%589.57 kB590.89 kB+0.22%103.80 kB104.03 kB
facebook-www/ReactDOM-prod.modern.js+0.23%565.41 kB566.73 kB+0.23%99.93 kB100.16 kB
test_utils/ReactAllWarnings.jsDeleted64.24 kB0.00 kBDeleted16.03 kB0.00 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name+/-BaseCurrent+/- gzipBase gzipCurrent gzip
oss-stable-semver/react-reconciler/cjs/react-reconciler.production.js+0.49%665.84 kB669.08 kB+0.51%146.23 kB146.97 kB
oss-stable/react-reconciler/cjs/react-reconciler.production.js+0.49%665.86 kB669.11 kB+0.51%146.26 kB147.01 kB
oss-experimental/react-reconciler/cjs/react-reconciler.production.js+0.48%672.88 kB676.12 kB+0.53%147.79 kB148.57 kB
oss-stable-semver/react-reconciler/cjs/react-reconciler.development.js+0.48%908.86 kB913.24 kB+0.53%195.30 kB196.34 kB
oss-stable/react-reconciler/cjs/react-reconciler.development.js+0.48%908.89 kB913.27 kB+0.53%195.33 kB196.37 kB
oss-experimental/react-reconciler/cjs/react-reconciler.development.js+0.48%918.20 kB922.58 kB+0.53%197.14 kB198.19 kB
oss-stable-semver/react-reconciler/cjs/react-reconciler.profiling.js+0.46%705.86 kB709.10 kB+0.50%153.52 kB154.29 kB
oss-stable/react-reconciler/cjs/react-reconciler.profiling.js+0.46%705.89 kB709.13 kB+0.50%153.55 kB154.31 kB
oss-experimental/react-reconciler/cjs/react-reconciler.profiling.js+0.46%712.90 kB716.14 kB+0.49%155.11 kB155.88 kB
oss-stable-semver/react-reconciler/cjs/react-reconciler.production.min.js+0.43%108.56 kB109.03 kB+0.39%33.85 kB33.98 kB
oss-stable/react-reconciler/cjs/react-reconciler.production.min.js+0.43%108.59 kB109.06 kB+0.39%33.87 kB34.00 kB
oss-experimental/react-reconciler/cjs/react-reconciler.production.min.js+0.42%110.35 kB110.82 kB+0.37%34.47 kB34.60 kB
oss-stable-semver/react-reconciler/cjs/react-reconciler.profiling.min.js+0.40%117.42 kB117.89 kB+0.32%36.09 kB36.21 kB
oss-stable/react-reconciler/cjs/react-reconciler.profiling.min.js+0.40%117.45 kB117.92 kB+0.33%36.11 kB36.23 kB
oss-experimental/react-reconciler/cjs/react-reconciler.profiling.min.js+0.39%119.21 kB119.67 kB+0.41%36.65 kB36.80 kB
oss-stable-semver/react-dom/cjs/react-dom.production.js+0.35%919.85 kB923.06 kB+0.37%206.89 kB207.65 kB
oss-stable/react-dom/cjs/react-dom.production.js+0.35%919.87 kB923.08 kB+0.37%206.92 kB207.68 kB
oss-experimental/react-dom/cjs/react-dom.production.js+0.35%926.94 kB930.15 kB+0.37%208.43 kB209.20 kB
oss-experimental/react-dom/cjs/react-dom-unstable_testing.production.js+0.34%945.18 kB948.39 kB+0.36%212.95 kB213.71 kB
oss-stable-semver/react-dom/cjs/react-dom.development.js+0.34%1,293.34 kB1,297.68 kB+0.37%286.49 kB287.55 kB
oss-stable/react-dom/cjs/react-dom.development.js+0.34%1,293.36 kB1,297.71 kB+0.37%286.52 kB287.58 kB
oss-stable-semver/react-dom/umd/react-dom.development.js+0.34%1,356.09 kB1,360.63 kB+0.38%289.40 kB290.49 kB
oss-stable/react-dom/umd/react-dom.development.js+0.34%1,356.12 kB1,360.66 kB+0.38%289.43 kB290.52 kB
oss-stable-semver/react-dom/cjs/react-dom.profiling.js+0.33%960.46 kB963.67 kB+0.35%214.16 kB214.92 kB
oss-stable/react-dom/cjs/react-dom.profiling.js+0.33%960.48 kB963.69 kB+0.35%214.19 kB214.95 kB
oss-experimental/react-dom/cjs/react-dom.development.js+0.33%1,302.73 kB1,307.08 kB+0.37%288.32 kB289.39 kB
oss-experimental/react-dom/umd/react-dom.development.js+0.33%1,365.97 kB1,370.51 kB+0.36%291.21 kB292.26 kB
oss-experimental/react-dom/cjs/react-dom.profiling.js+0.33%967.55 kB970.76 kB+0.35%215.71 kB216.46 kB
oss-experimental/react-dom/cjs/react-dom-unstable_testing.development.js+0.33%1,321.15 kB1,325.50 kB+0.37%292.77 kB293.84 kB
facebook-www/ReactDOM-dev.modern.js+0.30%1,621.20 kB1,626.01 kB+0.34%322.53 kB323.63 kB
facebook-www/ReactDOMTesting-dev.modern.js+0.29%1,644.60 kB1,649.41 kB+0.34%327.14 kB328.26 kB
facebook-www/ReactDOM-dev.classic.js+0.29%1,673.24 kB1,678.05 kB+0.34%331.38 kB332.50 kB
facebook-www/ReactDOMTesting-dev.classic.js+0.28%1,697.92 kB1,702.73 kB+0.33%336.19 kB337.31 kB
oss-stable-semver/react-dom/umd/react-dom.production.min.js+0.27%167.79 kB168.24 kB+0.28%53.04 kB53.19 kB
oss-stable/react-dom/umd/react-dom.production.min.js+0.27%167.87 kB168.32 kB+0.28%53.07 kB53.22 kB
oss-stable-semver/react-dom/cjs/react-dom.production.min.js+0.27%168.04 kB168.49 kB+0.24%52.69 kB52.82 kB
oss-stable/react-dom/cjs/react-dom.production.min.js+0.27%168.12 kB168.57 kB+0.24%52.72 kB52.85 kB
oss-experimental/react-dom/umd/react-dom.production.min.js+0.27%169.67 kB170.13 kB+0.25%53.70 kB53.83 kB
oss-experimental/react-dom/cjs/react-dom.production.min.js+0.26%169.92 kB170.37 kB+0.20%53.26 kB53.37 kB
oss-stable-semver/react-dom/umd/react-dom.profiling.min.js+0.25%176.63 kB177.08 kB+0.21%55.45 kB55.56 kB
oss-stable/react-dom/umd/react-dom.profiling.min.js+0.25%176.71 kB177.16 kB+0.21%55.47 kB55.59 kB
oss-experimental/react-dom/cjs/react-dom-unstable_testing.production.min.js+0.25%176.86 kB177.31 kB+0.20%55.85 kB55.97 kB
oss-stable-semver/react-dom/cjs/react-dom.profiling.min.js+0.25%177.32 kB177.77 kB+0.22%55.14 kB55.26 kB
oss-stable/react-dom/cjs/react-dom.profiling.min.js+0.25%177.40 kB177.85 kB+0.22%55.16 kB55.28 kB
oss-experimental/react-dom/umd/react-dom.profiling.min.js+0.25%178.51 kB178.96 kB+0.25%56.01 kB56.15 kB
oss-experimental/react-dom/cjs/react-dom.profiling.min.js+0.25%179.21 kB179.66 kB+0.25%55.71 kB55.85 kB
facebook-www/ReactDOM-prod.modern.js+0.23%565.41 kB566.73 kB+0.23%99.93 kB100.16 kB
facebook-www/ReactDOMTesting-prod.modern.js+0.23%581.36 kB582.67 kB+0.22%103.88 kB104.11 kB
facebook-www/ReactDOM-prod.classic.js+0.22%589.57 kB590.89 kB+0.22%103.80 kB104.03 kB
facebook-www/ReactDOM-profiling.modern.js+0.22%594.31 kB595.63 kB+0.22%104.07 kB104.29 kB
facebook-www/ReactDOMTesting-prod.classic.js+0.22%604.22 kB605.54 kB+0.21%107.51 kB107.74 kB
facebook-www/ReactDOM-profiling.classic.js+0.21%619.11 kB620.43 kB+0.22%108.10 kB108.33 kB
test_utils/ReactAllWarnings.jsDeleted64.24 kB0.00 kBDeleted16.03 kB0.00 kB

Generated by 🚫 dangerJS against 562f9c9

@acdlite
acdliteforce-pushed the automatically-reset-forms branch 2 times, most recently from 5e8fad4 to 41e6173CompareApril 10, 2024 00:38
@acdlite
acdlite marked this pull request as ready for review April 10, 2024 00:41

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should start a campaign for javascript64

@acdliteacdlite mentioned this pull request Apr 10, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right
in userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
@acdlite
acdliteforce-pushed the automatically-reset-forms branch from 41e6173 to 562f9c9CompareApril 10, 2024 04:04
const newResetState = {};
const resetStateHook: Hook = (formFiber.memoizedState.next: any);
const resetStateQueue = resetStateHook.queue;
dispatchSetState(formFiber, resetStateQueue, newResetState);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this actually have to be on the Fiber?

Can't it just be scheduled on the Root with a list of forms to reset when the root commits?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That way you don't need all the special commit phase stuff.

@acdliteacdliteApr 10, 2024

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm I'll need to think more about that, the scenario I had in mind was if the form is inside a Suspense boundary, the root could commit before the input's defaultValue had been updated. Usually this shouldn't happen because during a Transition we won't hide already visible forms, but during a popstate transition we might.

The <input form="myform"> case is interesting there, too.

@acdlite
acdlite merged commit 41950d1 into react:mainApr 10, 2024
acdlite added a commit that referenced this pull request Apr 10, 2024
Based on:
- #28804 ---
This sets adds a new ReactDOM export called requestFormReset, including
setting up the export and creating a method on the internal ReactDOM
dispatcher. It does not yet add any implementation.
Doing this in its own commit for review purposes.
The API itself will be explained in the next PR.
acdlite added a commit that referenced this pull request Apr 10, 2024
Based on:
- #28808
- #28804 ---
This adds a React DOM method called requestFormReset that schedules a
form reset to occur when the current transition completes.
Internally, it's the same method that's called automatically whenever a
form action is submitted. It only affects uncontrolled form inputs. See
#28804 for details.
The reason for the public API is so UI libraries can implement their own
action-based APIs and maintain the form-resetting behavior, something
like this:
```js
function onSubmit(event) {
// Disable default form submission behavior
event.preventDefault();
const form = event.target;
startTransition(async () => {
// Request the form to reset once the action
// has completed
requestFormReset(form);
// Call the user-provided action prop
await action(new FormData(form));
})
}
```
github-actionsBot pushed a commit that referenced this pull request Apr 10, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right in
userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
DiffTrain build for [41950d1](41950d1)
github-actionsBot pushed a commit that referenced this pull request Apr 10, 2024
Based on:
- #28804
---
This sets adds a new ReactDOM export called requestFormReset, including
setting up the export and creating a method on the internal ReactDOM
dispatcher. It does not yet add any implementation.
Doing this in its own commit for review purposes.
The API itself will be explained in the next PR.
DiffTrain build for [374b5d2](374b5d2)
github-actionsBot pushed a commit that referenced this pull request Apr 10, 2024
Based on:
- #28808
- #28804
---
This adds a React DOM method called requestFormReset that schedules a
form reset to occur when the current transition completes.
Internally, it's the same method that's called automatically whenever a
form action is submitted. It only affects uncontrolled form inputs. See
#28804 for details.
The reason for the public API is so UI libraries can implement their own
action-based APIs and maintain the form-resetting behavior, something
like this:
```js
function onSubmit(event) {
// Disable default form submission behavior
event.preventDefault();
const form = event.target;
startTransition(async () => {
// Request the form to reset once the action
// has completed
requestFormReset(form);
// Call the user-provided action prop
await action(new FormData(form));
})
}
```
DiffTrain build for [da69b6a](da69b6a)
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right in
userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
Based on:
- #28804 ---
This sets adds a new ReactDOM export called requestFormReset, including
setting up the export and creating a method on the internal ReactDOM
dispatcher. It does not yet add any implementation.
Doing this in its own commit for review purposes.
The API itself will be explained in the next PR.
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
Based on:
- #28808
- #28804 ---
This adds a React DOM method called requestFormReset that schedules a
form reset to occur when the current transition completes.
Internally, it's the same method that's called automatically whenever a
form action is submitted. It only affects uncontrolled form inputs. See
#28804 for details.
The reason for the public API is so UI libraries can implement their own
action-based APIs and maintain the form-resetting behavior, something
like this:
```js
function onSubmit(event) {
// Disable default form submission behavior
event.preventDefault();
const form = event.target;
startTransition(async () => {
// Request the form to reset once the action
// has completed
requestFormReset(form);
// Call the user-provided action prop
await action(new FormData(form));
})
}
```
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right in
userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
Based on:
- #28804 ---
This sets adds a new ReactDOM export called requestFormReset, including
setting up the export and creating a method on the internal ReactDOM
dispatcher. It does not yet add any implementation.
Doing this in its own commit for review purposes.
The API itself will be explained in the next PR.
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
Based on:
- #28808
- #28804 ---
This adds a React DOM method called requestFormReset that schedules a
form reset to occur when the current transition completes.
Internally, it's the same method that's called automatically whenever a
form action is submitted. It only affects uncontrolled form inputs. See
#28804 for details.
The reason for the public API is so UI libraries can implement their own
action-based APIs and maintain the form-resetting behavior, something
like this:
```js
function onSubmit(event) {
// Disable default form submission behavior
event.preventDefault();
const form = event.target;
startTransition(async () => {
// Request the form to reset once the action
// has completed
requestFormReset(form);
// Call the user-provided action prop
await action(new FormData(form));
})
}
```
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right in
userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
Based on:
- react#28804 ---
This sets adds a new ReactDOM export called requestFormReset, including
setting up the export and creating a method on the internal ReactDOM
dispatcher. It does not yet add any implementation.
Doing this in its own commit for review purposes.
The API itself will be explained in the next PR.
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
Based on:
- react#28808
- react#28804 ---
This adds a React DOM method called requestFormReset that schedules a
form reset to occur when the current transition completes.
Internally, it's the same method that's called automatically whenever a
form action is submitted. It only affects uncontrolled form inputs. See
react#28804 for details.
The reason for the public API is so UI libraries can implement their own
action-based APIs and maintain the form-resetting behavior, something
like this:
```js
function onSubmit(event) {
// Disable default form submission behavior
event.preventDefault();
const form = event.target;
startTransition(async () => {
// Request the form to reset once the action
// has completed
requestFormReset(form);
// Call the user-provided action prop
await action(new FormData(form));
})
}
```
bigfootjon pushed a commit that referenced this pull request Apr 18, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right in
userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
DiffTrain build for commit 41950d1.
facebook-github-bot pushed a commit to react/react-native that referenced this pull request Apr 19, 2024
Summary:
This sync includes the changes from:
- D56103750
- [TODO] A shim for SECRET_INTERNALS
This sync includes the following changes:
- **[b5e5ce8](react/react@b5e5ce8e0 )**: Update ReactNativeTypes for root options (part 2) ([#28857](react/react#28857)) //<Ricky>//
- **[da6ba53](react/react@da6ba53b1 )**: [UMD] Remove umd builds ([#28735](react/react#28735)) //<Josh Story>//
- **[0c245df](react/react@0c245df1d )**: Complete the typo fix ([#28856](react/react#28856)) //<Sebastian Silbermann>//
- **[f82051d](react/react@f82051d7a )**: console test utils fix: match entire string, not just first letter ([#28855](react/react#28855)) //<Andrew Clark>//
- **[4ca20fd](react/react@4ca20fd36 )**: Test top level fragment inside lazy semantics ([#28852](react/react#28852)) //<Sebastian Markbåge>//
- **[c0cf7c6](react/react@c0cf7c696 )**: Promote ASYNC_ITERATOR symbol to React Symbols ([#28851](react/react#28851)) //<Sebastian Markbåge>//
- **[657428a](react/react@657428a9e )**: Add ReactNativeTypes for root options ([#28850](react/react#28850)) //<Ricky>//
- **[7909d8e](react/react@7909d8eab )**: [Flight] Encode ReadableStream and AsyncIterables ([#28847](react/react#28847)) //<Sebastian Markbåge>//
- **[13eb61d](react/react@13eb61d05 )**: Move enableUseDeferredValueInitialArg to canary ([#28818](react/react#28818)) //<Andrew Clark>//
- **[8afa144](react/react@8afa144bd )**: Enable flag disableClientCache ([#28846](react/react#28846)) //<Jan Kassens>//
- **[734956a](react/react@734956ace )**: Devtools: Add support for useFormStatus ([#28413](react/react#28413)) //<Sebastian Silbermann>//
- **[17e920c](react/react@17e920c00 )**: [Flight Reply] Encode Typed Arrays and Blobs ([#28819](react/react#28819)) //<Sebastian Markbåge>//
- **[0347fcd](react/react@0347fcd00 )**: Add on(Caught|Uncaught|Recoverable) opts to RN ([#28836](react/react#28836)) //<Ricky>//
- **[c113503](react/react@c113503ad )**: Flush direct streams in Bun ([#28837](react/react#28837)) //<Kenta Iwasaki>//
- **[9defcd5](react/react@9defcd56b )**: Remove redundant props assign ([#28829](react/react#28829)) //<Sebastian Silbermann>//
- **[ed40236](react/react@ed4023603 )**: Fix mistaken "react-server" condition ([#28835](react/react#28835)) //<Sebastian Markbåge>//
- **[c8a0350](react/react@c8a035036 )**: [Fizz] hoistables should never flush before the preamble ([#28802](react/react#28802)) //<Josh Story>//
- **[4f5c812](react/react@4f5c812a3 )**: DevTools: Rely on sourcemaps to compute hook name of built-in hooks in newer versions ([#28593](react/react#28593)) //<Sebastian Silbermann>//
- **[4354159](react/react@435415962 )**: Backwards compatibility for string refs on WWW ([#28826](react/react#28826)) //<Jack Pope>//
- **[608edcc](react/react@608edcc90 )**: [tests] add `assertConsole<method>Dev` helpers ([#28732](react/react#28732)) //<Ricky>//
- **[da69b6a](react/react@da69b6af9 )**: ReactDOM.requestFormReset ([#28809](react/react#28809)) //<Andrew Clark>//
- **[374b5d2](react/react@374b5d26c )**: Scaffolding for requestFormReset API ([#28808](react/react#28808)) //<Andrew Clark>//
- **[41950d1](react/react@41950d14a )**: Automatically reset forms after action finishes ([#28804](react/react#28804)) //<Andrew Clark>//
- **[dc6a7e0](react/react@dc6a7e01e )**: [Float] Don't preload images inside `<noscript>` ([#28815](react/react#28815)) //<Josh Story>//
- **[3f947b1](react/react@3f947b1b4 )**: [tests] Assert scheduler log empty in internalAct ([#28737](react/react#28737)) //<Ricky>//
- **[bf09089](react/react@bf09089f6 )**: Remove Scheduler.log from ReactSuspenseFuzz-test ([#28812](react/react#28812)) //<Ricky>//
- **[84cb3b4](react/react@84cb3b4cb )**: Hardcode disableIEWorkarounds for www ([#28811](react/react#28811)) //<Ricky>//
- **[2243b40](react/react@2243b40ab )**: [tests] assertLog before act in useEffectEvent ([#28763](react/react#28763)) //<Ricky>//
- **[dfc64c6](react/react@dfc64c6e3 )**: [tests] assertLog before act in ReactUse ([#28762](react/react#28762)) //<Ricky>//
- **[42eff4b](react/react@42eff4bc7 )**: [tests] Fix assertions not flushed before act ([#28745](react/react#28745)) //<Ricky>//
- **[ed3c65c](react/react@ed3c65caf )**: Warn if outdated JSX transform is detected ([#28781](react/react#28781)) //<Andrew Clark>//
- **[3f9e237](react/react@3f9e237a2 )**: Fix: Suspend while recovering from hydration error ([#28800](react/react#28800)) //<Andrew Clark>//
- **[7f5d25e](react/react@7f5d25e23 )**: Fix cloneElement using string ref w no owner ([#28797](react/react#28797)) //<Joseph Savona>//
- **[bf40b02](react/react@bf40b0244 )**: [Fizz] Stop publishing external-runtime to stable channel ([#28796](react/react#28796)) //<Josh Story>//
- **[7f93cb4](react/react@7f93cb41c )**: [DOM] Infer react-server entries bundles if not explicitly configured ([#28795](react/react#28795)) //<Josh Story>//
- **[f613165](react/react@f61316535 )**: Rename SECRET INTERNALS to `__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE` ([#28789](react/react#28789)) //<Sebastian Markbåge>//
- **[9644d20](react/react@9644d206e )**: Soften useFormState warning ([#28788](react/react#28788)) //<Ricky>//
- **[c771016](react/react@c771016e1 )**: Rename The Secret Export of Server Internals ([#28786](react/react#28786)) //<Sebastian Markbåge>//
- **[d50323e](react/react@d50323eb8 )**: Flatten ReactSharedInternals ([#28783](react/react#28783)) //<Sebastian Markbåge>//
- **[f62cf8c](react/react@f62cf8c62 )**: [Float] treat `props.async` in Float consistent with the rest of react-dom ([#26760](react/react#26760)) //<Josh Story>//
- **[dfd3d5a](react/react@dfd3d5af8 )**: Add support for transition{run,start,cancel} events ([#27345](react/react#27345)) //<Hugo Sales>//
- **[1f8327f](react/react@1f8327f83 )**: [Fiber] Use real event priority for hydration scheduling ([#28765](react/react#28765)) //<Josh Story>//
- **[97c90ed](react/react@97c90ed88 )**: [DOM] Shrink ReactDOMCurrentDispatcher method names ([#28770](react/react#28770)) //<Josh Story>//
- **[9007fdc](react/react@9007fdc8f )**: [DOM] Shrink ReactDOMSharedInternals source representation ([#28771](react/react#28771)) //<Josh Story>//
- **[14f50ad](react/react@14f50ad15 )**: [Flight] Allow lazily resolving outlined models ([#28780](react/react#28780)) //<Sebastian Markbåge>//
- **[4c12339](react/react@4c12339ce )**: [DOM] move `flushSync` out of the reconciler ([#28500](react/react#28500)) //<Josh Story>//
- **[8e1462e](react/react@8e1462e8c )**: [Fiber] Move updatePriority tracking to renderers ([#28751](react/react#28751)) //<Josh Story>//
- **[0b3b8a6](react/react@0b3b8a6a3 )**: jsx: Remove unnecessary hasOwnProperty check ([#28775](react/react#28775)) //<Andrew Clark>//
- **[2acfb7b](react/react@2acfb7b60 )**: [Flight] Support FormData from Server to Client ([#28754](react/react#28754)) //<Sebastian Markbåge>//
- **[d1547de](react/react@d1547defe )**: Fast JSX: Don't clone props object ([#28768](react/react#28768)) //<Andrew Clark>//
- **[bfd8da8](react/react@bfd8da807 )**: Make class prop resolution faster ([#28766](react/react#28766)) //<Andrew Clark>//
- **[cbb6f2b](react/react@cbb6f2b54 )**: [Flight] Support Blobs from Server to Client ([#28755](react/react#28755)) //<Sebastian Markbåge>//
- **[f33a6b6](react/react@f33a6b69c )**: Track Owner for Server Components in DEV ([#28753](react/react#28753)) //<Sebastian Markbåge>//
- **[e3ebcd5](react/react@e3ebcd54b )**: Move string ref coercion to JSX runtime ([#28473](react/react#28473)) //<Andrew Clark>//
- **[fd0da3e](react/react@fd0da3eef )**: Remove _owner field from JSX elements in prod if string refs are disabled ([#28739](react/react#28739)) //<Sebastian Markbåge>//
Changelog:
[General][Changed] - React Native sync for revisions 48b4ecc...b5e5ce8
jest_e2e[run_all_tests]
bypass-github-export-checks
Reviewed By: kassens
Differential Revision: D56251607
fbshipit-source-id: e16db2fa101fc7ed1e009158c76388206beabd5f
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA SignedReact Core TeamOpened by a member of the React Core Team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@acdlite@react-sizebot@sebmarkbage@gnoff@facebook-github-bot
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Automatically reset forms after action finishes - #28804

Merged
acdlite merged 1 commit into
react:mainfrom
acdlite:automatically-reset-forms
Apr 10, 2024
Merged

Automatically reset forms after action finishes#28804
acdlite merged 1 commit into
react:mainfrom
acdlite:automatically-reset-forms

Conversation

@acdlite

Copy link
Copy Markdown
Collaborator

This updates the behavior of form actions to automatically reset the form's uncontrolled inputs after the action finishes.

This is a frequent feature request for people using actions and it aligns the behavior of client-side form submissions more closely with MPA form submissions.

It has no impact on controlled form inputs. It's the same as if you called form.reset() manually, except React handles the timing of when the reset happens, which is tricky/impossible to get exactly right in userspace.

The reset shouldn't happen until the UI has updated with the result of the action. So, resetting inside the action is too early.

Resetting in useEffect is better, but it's later than ideal because any effects that run before it will observe the state of the form before it's been reset.

It needs to happen in the mutation phase of the transition. More specifically, after all the DOM mutations caused by the transition have been applied. That way the defaultValue of the inputs are updated before the values are reset. The idea is that the defaultValue represents the current, canonical value sent by the server.

Note: this change has no effect on form submissions that aren't triggered by an action.

@facebook-github-botfacebook-github-bot added CLA Signed React Core Team Opened by a member of the React Core Team labels Apr 10, 2024
@react-sizebot

react-sizebot commented Apr 10, 2024

Copy link
Copy Markdown

Comparing: ed3c65c...562f9c9

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name+/-BaseCurrent+/- gzipBase gzipCurrent gzip
oss-stable/react-dom/cjs/react-dom.production.min.js+0.27%168.12 kB168.57 kB+0.24%52.72 kB52.85 kB
oss-experimental/react-dom/cjs/react-dom.production.min.js+0.26%169.92 kB170.37 kB+0.20%53.26 kB53.37 kB
facebook-www/ReactDOM-prod.classic.js+0.22%589.57 kB590.89 kB+0.22%103.80 kB104.03 kB
facebook-www/ReactDOM-prod.modern.js+0.23%565.41 kB566.73 kB+0.23%99.93 kB100.16 kB
test_utils/ReactAllWarnings.jsDeleted64.24 kB0.00 kBDeleted16.03 kB0.00 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name+/-BaseCurrent+/- gzipBase gzipCurrent gzip
oss-stable-semver/react-reconciler/cjs/react-reconciler.production.js+0.49%665.84 kB669.08 kB+0.51%146.23 kB146.97 kB
oss-stable/react-reconciler/cjs/react-reconciler.production.js+0.49%665.86 kB669.11 kB+0.51%146.26 kB147.01 kB
oss-experimental/react-reconciler/cjs/react-reconciler.production.js+0.48%672.88 kB676.12 kB+0.53%147.79 kB148.57 kB
oss-stable-semver/react-reconciler/cjs/react-reconciler.development.js+0.48%908.86 kB913.24 kB+0.53%195.30 kB196.34 kB
oss-stable/react-reconciler/cjs/react-reconciler.development.js+0.48%908.89 kB913.27 kB+0.53%195.33 kB196.37 kB
oss-experimental/react-reconciler/cjs/react-reconciler.development.js+0.48%918.20 kB922.58 kB+0.53%197.14 kB198.19 kB
oss-stable-semver/react-reconciler/cjs/react-reconciler.profiling.js+0.46%705.86 kB709.10 kB+0.50%153.52 kB154.29 kB
oss-stable/react-reconciler/cjs/react-reconciler.profiling.js+0.46%705.89 kB709.13 kB+0.50%153.55 kB154.31 kB
oss-experimental/react-reconciler/cjs/react-reconciler.profiling.js+0.46%712.90 kB716.14 kB+0.49%155.11 kB155.88 kB
oss-stable-semver/react-reconciler/cjs/react-reconciler.production.min.js+0.43%108.56 kB109.03 kB+0.39%33.85 kB33.98 kB
oss-stable/react-reconciler/cjs/react-reconciler.production.min.js+0.43%108.59 kB109.06 kB+0.39%33.87 kB34.00 kB
oss-experimental/react-reconciler/cjs/react-reconciler.production.min.js+0.42%110.35 kB110.82 kB+0.37%34.47 kB34.60 kB
oss-stable-semver/react-reconciler/cjs/react-reconciler.profiling.min.js+0.40%117.42 kB117.89 kB+0.32%36.09 kB36.21 kB
oss-stable/react-reconciler/cjs/react-reconciler.profiling.min.js+0.40%117.45 kB117.92 kB+0.33%36.11 kB36.23 kB
oss-experimental/react-reconciler/cjs/react-reconciler.profiling.min.js+0.39%119.21 kB119.67 kB+0.41%36.65 kB36.80 kB
oss-stable-semver/react-dom/cjs/react-dom.production.js+0.35%919.85 kB923.06 kB+0.37%206.89 kB207.65 kB
oss-stable/react-dom/cjs/react-dom.production.js+0.35%919.87 kB923.08 kB+0.37%206.92 kB207.68 kB
oss-experimental/react-dom/cjs/react-dom.production.js+0.35%926.94 kB930.15 kB+0.37%208.43 kB209.20 kB
oss-experimental/react-dom/cjs/react-dom-unstable_testing.production.js+0.34%945.18 kB948.39 kB+0.36%212.95 kB213.71 kB
oss-stable-semver/react-dom/cjs/react-dom.development.js+0.34%1,293.34 kB1,297.68 kB+0.37%286.49 kB287.55 kB
oss-stable/react-dom/cjs/react-dom.development.js+0.34%1,293.36 kB1,297.71 kB+0.37%286.52 kB287.58 kB
oss-stable-semver/react-dom/umd/react-dom.development.js+0.34%1,356.09 kB1,360.63 kB+0.38%289.40 kB290.49 kB
oss-stable/react-dom/umd/react-dom.development.js+0.34%1,356.12 kB1,360.66 kB+0.38%289.43 kB290.52 kB
oss-stable-semver/react-dom/cjs/react-dom.profiling.js+0.33%960.46 kB963.67 kB+0.35%214.16 kB214.92 kB
oss-stable/react-dom/cjs/react-dom.profiling.js+0.33%960.48 kB963.69 kB+0.35%214.19 kB214.95 kB
oss-experimental/react-dom/cjs/react-dom.development.js+0.33%1,302.73 kB1,307.08 kB+0.37%288.32 kB289.39 kB
oss-experimental/react-dom/umd/react-dom.development.js+0.33%1,365.97 kB1,370.51 kB+0.36%291.21 kB292.26 kB
oss-experimental/react-dom/cjs/react-dom.profiling.js+0.33%967.55 kB970.76 kB+0.35%215.71 kB216.46 kB
oss-experimental/react-dom/cjs/react-dom-unstable_testing.development.js+0.33%1,321.15 kB1,325.50 kB+0.37%292.77 kB293.84 kB
facebook-www/ReactDOM-dev.modern.js+0.30%1,621.20 kB1,626.01 kB+0.34%322.53 kB323.63 kB
facebook-www/ReactDOMTesting-dev.modern.js+0.29%1,644.60 kB1,649.41 kB+0.34%327.14 kB328.26 kB
facebook-www/ReactDOM-dev.classic.js+0.29%1,673.24 kB1,678.05 kB+0.34%331.38 kB332.50 kB
facebook-www/ReactDOMTesting-dev.classic.js+0.28%1,697.92 kB1,702.73 kB+0.33%336.19 kB337.31 kB
oss-stable-semver/react-dom/umd/react-dom.production.min.js+0.27%167.79 kB168.24 kB+0.28%53.04 kB53.19 kB
oss-stable/react-dom/umd/react-dom.production.min.js+0.27%167.87 kB168.32 kB+0.28%53.07 kB53.22 kB
oss-stable-semver/react-dom/cjs/react-dom.production.min.js+0.27%168.04 kB168.49 kB+0.24%52.69 kB52.82 kB
oss-stable/react-dom/cjs/react-dom.production.min.js+0.27%168.12 kB168.57 kB+0.24%52.72 kB52.85 kB
oss-experimental/react-dom/umd/react-dom.production.min.js+0.27%169.67 kB170.13 kB+0.25%53.70 kB53.83 kB
oss-experimental/react-dom/cjs/react-dom.production.min.js+0.26%169.92 kB170.37 kB+0.20%53.26 kB53.37 kB
oss-stable-semver/react-dom/umd/react-dom.profiling.min.js+0.25%176.63 kB177.08 kB+0.21%55.45 kB55.56 kB
oss-stable/react-dom/umd/react-dom.profiling.min.js+0.25%176.71 kB177.16 kB+0.21%55.47 kB55.59 kB
oss-experimental/react-dom/cjs/react-dom-unstable_testing.production.min.js+0.25%176.86 kB177.31 kB+0.20%55.85 kB55.97 kB
oss-stable-semver/react-dom/cjs/react-dom.profiling.min.js+0.25%177.32 kB177.77 kB+0.22%55.14 kB55.26 kB
oss-stable/react-dom/cjs/react-dom.profiling.min.js+0.25%177.40 kB177.85 kB+0.22%55.16 kB55.28 kB
oss-experimental/react-dom/umd/react-dom.profiling.min.js+0.25%178.51 kB178.96 kB+0.25%56.01 kB56.15 kB
oss-experimental/react-dom/cjs/react-dom.profiling.min.js+0.25%179.21 kB179.66 kB+0.25%55.71 kB55.85 kB
facebook-www/ReactDOM-prod.modern.js+0.23%565.41 kB566.73 kB+0.23%99.93 kB100.16 kB
facebook-www/ReactDOMTesting-prod.modern.js+0.23%581.36 kB582.67 kB+0.22%103.88 kB104.11 kB
facebook-www/ReactDOM-prod.classic.js+0.22%589.57 kB590.89 kB+0.22%103.80 kB104.03 kB
facebook-www/ReactDOM-profiling.modern.js+0.22%594.31 kB595.63 kB+0.22%104.07 kB104.29 kB
facebook-www/ReactDOMTesting-prod.classic.js+0.22%604.22 kB605.54 kB+0.21%107.51 kB107.74 kB
facebook-www/ReactDOM-profiling.classic.js+0.21%619.11 kB620.43 kB+0.22%108.10 kB108.33 kB
test_utils/ReactAllWarnings.jsDeleted64.24 kB0.00 kBDeleted16.03 kB0.00 kB

Generated by 🚫 dangerJS against 562f9c9

@acdlite
acdliteforce-pushed the automatically-reset-forms branch 2 times, most recently from 5e8fad4 to 41e6173CompareApril 10, 2024 00:38
@acdlite
acdlite marked this pull request as ready for review April 10, 2024 00:41

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should start a campaign for javascript64

@acdliteacdlite mentioned this pull request Apr 10, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right
in userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
@acdlite
acdliteforce-pushed the automatically-reset-forms branch from 41e6173 to 562f9c9CompareApril 10, 2024 04:04
const newResetState = {};
const resetStateHook: Hook = (formFiber.memoizedState.next: any);
const resetStateQueue = resetStateHook.queue;
dispatchSetState(formFiber, resetStateQueue, newResetState);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this actually have to be on the Fiber?

Can't it just be scheduled on the Root with a list of forms to reset when the root commits?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That way you don't need all the special commit phase stuff.

@acdliteacdliteApr 10, 2024

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm I'll need to think more about that, the scenario I had in mind was if the form is inside a Suspense boundary, the root could commit before the input's defaultValue had been updated. Usually this shouldn't happen because during a Transition we won't hide already visible forms, but during a popstate transition we might.

The <input form="myform"> case is interesting there, too.

@acdlite
acdlite merged commit 41950d1 into react:mainApr 10, 2024
acdlite added a commit that referenced this pull request Apr 10, 2024
Based on:
- #28804 ---
This sets adds a new ReactDOM export called requestFormReset, including
setting up the export and creating a method on the internal ReactDOM
dispatcher. It does not yet add any implementation.
Doing this in its own commit for review purposes.
The API itself will be explained in the next PR.
acdlite added a commit that referenced this pull request Apr 10, 2024
Based on:
- #28808
- #28804 ---
This adds a React DOM method called requestFormReset that schedules a
form reset to occur when the current transition completes.
Internally, it's the same method that's called automatically whenever a
form action is submitted. It only affects uncontrolled form inputs. See
#28804 for details.
The reason for the public API is so UI libraries can implement their own
action-based APIs and maintain the form-resetting behavior, something
like this:
```js
function onSubmit(event) {
// Disable default form submission behavior
event.preventDefault();
const form = event.target;
startTransition(async () => {
// Request the form to reset once the action
// has completed
requestFormReset(form);
// Call the user-provided action prop
await action(new FormData(form));
})
}
```
github-actionsBot pushed a commit that referenced this pull request Apr 10, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right in
userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
DiffTrain build for [41950d1](41950d1)
github-actionsBot pushed a commit that referenced this pull request Apr 10, 2024
Based on:
- #28804
---
This sets adds a new ReactDOM export called requestFormReset, including
setting up the export and creating a method on the internal ReactDOM
dispatcher. It does not yet add any implementation.
Doing this in its own commit for review purposes.
The API itself will be explained in the next PR.
DiffTrain build for [374b5d2](374b5d2)
github-actionsBot pushed a commit that referenced this pull request Apr 10, 2024
Based on:
- #28808
- #28804
---
This adds a React DOM method called requestFormReset that schedules a
form reset to occur when the current transition completes.
Internally, it's the same method that's called automatically whenever a
form action is submitted. It only affects uncontrolled form inputs. See
#28804 for details.
The reason for the public API is so UI libraries can implement their own
action-based APIs and maintain the form-resetting behavior, something
like this:
```js
function onSubmit(event) {
// Disable default form submission behavior
event.preventDefault();
const form = event.target;
startTransition(async () => {
// Request the form to reset once the action
// has completed
requestFormReset(form);
// Call the user-provided action prop
await action(new FormData(form));
})
}
```
DiffTrain build for [da69b6a](da69b6a)
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right in
userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
Based on:
- #28804 ---
This sets adds a new ReactDOM export called requestFormReset, including
setting up the export and creating a method on the internal ReactDOM
dispatcher. It does not yet add any implementation.
Doing this in its own commit for review purposes.
The API itself will be explained in the next PR.
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
Based on:
- #28808
- #28804 ---
This adds a React DOM method called requestFormReset that schedules a
form reset to occur when the current transition completes.
Internally, it's the same method that's called automatically whenever a
form action is submitted. It only affects uncontrolled form inputs. See
#28804 for details.
The reason for the public API is so UI libraries can implement their own
action-based APIs and maintain the form-resetting behavior, something
like this:
```js
function onSubmit(event) {
// Disable default form submission behavior
event.preventDefault();
const form = event.target;
startTransition(async () => {
// Request the form to reset once the action
// has completed
requestFormReset(form);
// Call the user-provided action prop
await action(new FormData(form));
})
}
```
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right in
userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
Based on:
- #28804 ---
This sets adds a new ReactDOM export called requestFormReset, including
setting up the export and creating a method on the internal ReactDOM
dispatcher. It does not yet add any implementation.
Doing this in its own commit for review purposes.
The API itself will be explained in the next PR.
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
Based on:
- #28808
- #28804 ---
This adds a React DOM method called requestFormReset that schedules a
form reset to occur when the current transition completes.
Internally, it's the same method that's called automatically whenever a
form action is submitted. It only affects uncontrolled form inputs. See
#28804 for details.
The reason for the public API is so UI libraries can implement their own
action-based APIs and maintain the form-resetting behavior, something
like this:
```js
function onSubmit(event) {
// Disable default form submission behavior
event.preventDefault();
const form = event.target;
startTransition(async () => {
// Request the form to reset once the action
// has completed
requestFormReset(form);
// Call the user-provided action prop
await action(new FormData(form));
})
}
```
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right in
userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
Based on:
- react#28804 ---
This sets adds a new ReactDOM export called requestFormReset, including
setting up the export and creating a method on the internal ReactDOM
dispatcher. It does not yet add any implementation.
Doing this in its own commit for review purposes.
The API itself will be explained in the next PR.
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
Based on:
- react#28808
- react#28804 ---
This adds a React DOM method called requestFormReset that schedules a
form reset to occur when the current transition completes.
Internally, it's the same method that's called automatically whenever a
form action is submitted. It only affects uncontrolled form inputs. See
react#28804 for details.
The reason for the public API is so UI libraries can implement their own
action-based APIs and maintain the form-resetting behavior, something
like this:
```js
function onSubmit(event) {
// Disable default form submission behavior
event.preventDefault();
const form = event.target;
startTransition(async () => {
// Request the form to reset once the action
// has completed
requestFormReset(form);
// Call the user-provided action prop
await action(new FormData(form));
})
}
```
bigfootjon pushed a commit that referenced this pull request Apr 18, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right in
userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
DiffTrain build for commit 41950d1.
facebook-github-bot pushed a commit to react/react-native that referenced this pull request Apr 19, 2024
Summary:
This sync includes the changes from:
- D56103750
- [TODO] A shim for SECRET_INTERNALS
This sync includes the following changes:
- **[b5e5ce8](react/react@b5e5ce8e0 )**: Update ReactNativeTypes for root options (part 2) ([#28857](react/react#28857)) //<Ricky>//
- **[da6ba53](react/react@da6ba53b1 )**: [UMD] Remove umd builds ([#28735](react/react#28735)) //<Josh Story>//
- **[0c245df](react/react@0c245df1d )**: Complete the typo fix ([#28856](react/react#28856)) //<Sebastian Silbermann>//
- **[f82051d](react/react@f82051d7a )**: console test utils fix: match entire string, not just first letter ([#28855](react/react#28855)) //<Andrew Clark>//
- **[4ca20fd](react/react@4ca20fd36 )**: Test top level fragment inside lazy semantics ([#28852](react/react#28852)) //<Sebastian Markbåge>//
- **[c0cf7c6](react/react@c0cf7c696 )**: Promote ASYNC_ITERATOR symbol to React Symbols ([#28851](react/react#28851)) //<Sebastian Markbåge>//
- **[657428a](react/react@657428a9e )**: Add ReactNativeTypes for root options ([#28850](react/react#28850)) //<Ricky>//
- **[7909d8e](react/react@7909d8eab )**: [Flight] Encode ReadableStream and AsyncIterables ([#28847](react/react#28847)) //<Sebastian Markbåge>//
- **[13eb61d](react/react@13eb61d05 )**: Move enableUseDeferredValueInitialArg to canary ([#28818](react/react#28818)) //<Andrew Clark>//
- **[8afa144](react/react@8afa144bd )**: Enable flag disableClientCache ([#28846](react/react#28846)) //<Jan Kassens>//
- **[734956a](react/react@734956ace )**: Devtools: Add support for useFormStatus ([#28413](react/react#28413)) //<Sebastian Silbermann>//
- **[17e920c](react/react@17e920c00 )**: [Flight Reply] Encode Typed Arrays and Blobs ([#28819](react/react#28819)) //<Sebastian Markbåge>//
- **[0347fcd](react/react@0347fcd00 )**: Add on(Caught|Uncaught|Recoverable) opts to RN ([#28836](react/react#28836)) //<Ricky>//
- **[c113503](react/react@c113503ad )**: Flush direct streams in Bun ([#28837](react/react#28837)) //<Kenta Iwasaki>//
- **[9defcd5](react/react@9defcd56b )**: Remove redundant props assign ([#28829](react/react#28829)) //<Sebastian Silbermann>//
- **[ed40236](react/react@ed4023603 )**: Fix mistaken "react-server" condition ([#28835](react/react#28835)) //<Sebastian Markbåge>//
- **[c8a0350](react/react@c8a035036 )**: [Fizz] hoistables should never flush before the preamble ([#28802](react/react#28802)) //<Josh Story>//
- **[4f5c812](react/react@4f5c812a3 )**: DevTools: Rely on sourcemaps to compute hook name of built-in hooks in newer versions ([#28593](react/react#28593)) //<Sebastian Silbermann>//
- **[4354159](react/react@435415962 )**: Backwards compatibility for string refs on WWW ([#28826](react/react#28826)) //<Jack Pope>//
- **[608edcc](react/react@608edcc90 )**: [tests] add `assertConsole<method>Dev` helpers ([#28732](react/react#28732)) //<Ricky>//
- **[da69b6a](react/react@da69b6af9 )**: ReactDOM.requestFormReset ([#28809](react/react#28809)) //<Andrew Clark>//
- **[374b5d2](react/react@374b5d26c )**: Scaffolding for requestFormReset API ([#28808](react/react#28808)) //<Andrew Clark>//
- **[41950d1](react/react@41950d14a )**: Automatically reset forms after action finishes ([#28804](react/react#28804)) //<Andrew Clark>//
- **[dc6a7e0](react/react@dc6a7e01e )**: [Float] Don't preload images inside `<noscript>` ([#28815](react/react#28815)) //<Josh Story>//
- **[3f947b1](react/react@3f947b1b4 )**: [tests] Assert scheduler log empty in internalAct ([#28737](react/react#28737)) //<Ricky>//
- **[bf09089](react/react@bf09089f6 )**: Remove Scheduler.log from ReactSuspenseFuzz-test ([#28812](react/react#28812)) //<Ricky>//
- **[84cb3b4](react/react@84cb3b4cb )**: Hardcode disableIEWorkarounds for www ([#28811](react/react#28811)) //<Ricky>//
- **[2243b40](react/react@2243b40ab )**: [tests] assertLog before act in useEffectEvent ([#28763](react/react#28763)) //<Ricky>//
- **[dfc64c6](react/react@dfc64c6e3 )**: [tests] assertLog before act in ReactUse ([#28762](react/react#28762)) //<Ricky>//
- **[42eff4b](react/react@42eff4bc7 )**: [tests] Fix assertions not flushed before act ([#28745](react/react#28745)) //<Ricky>//
- **[ed3c65c](react/react@ed3c65caf )**: Warn if outdated JSX transform is detected ([#28781](react/react#28781)) //<Andrew Clark>//
- **[3f9e237](react/react@3f9e237a2 )**: Fix: Suspend while recovering from hydration error ([#28800](react/react#28800)) //<Andrew Clark>//
- **[7f5d25e](react/react@7f5d25e23 )**: Fix cloneElement using string ref w no owner ([#28797](react/react#28797)) //<Joseph Savona>//
- **[bf40b02](react/react@bf40b0244 )**: [Fizz] Stop publishing external-runtime to stable channel ([#28796](react/react#28796)) //<Josh Story>//
- **[7f93cb4](react/react@7f93cb41c )**: [DOM] Infer react-server entries bundles if not explicitly configured ([#28795](react/react#28795)) //<Josh Story>//
- **[f613165](react/react@f61316535 )**: Rename SECRET INTERNALS to `__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE` ([#28789](react/react#28789)) //<Sebastian Markbåge>//
- **[9644d20](react/react@9644d206e )**: Soften useFormState warning ([#28788](react/react#28788)) //<Ricky>//
- **[c771016](react/react@c771016e1 )**: Rename The Secret Export of Server Internals ([#28786](react/react#28786)) //<Sebastian Markbåge>//
- **[d50323e](react/react@d50323eb8 )**: Flatten ReactSharedInternals ([#28783](react/react#28783)) //<Sebastian Markbåge>//
- **[f62cf8c](react/react@f62cf8c62 )**: [Float] treat `props.async` in Float consistent with the rest of react-dom ([#26760](react/react#26760)) //<Josh Story>//
- **[dfd3d5a](react/react@dfd3d5af8 )**: Add support for transition{run,start,cancel} events ([#27345](react/react#27345)) //<Hugo Sales>//
- **[1f8327f](react/react@1f8327f83 )**: [Fiber] Use real event priority for hydration scheduling ([#28765](react/react#28765)) //<Josh Story>//
- **[97c90ed](react/react@97c90ed88 )**: [DOM] Shrink ReactDOMCurrentDispatcher method names ([#28770](react/react#28770)) //<Josh Story>//
- **[9007fdc](react/react@9007fdc8f )**: [DOM] Shrink ReactDOMSharedInternals source representation ([#28771](react/react#28771)) //<Josh Story>//
- **[14f50ad](react/react@14f50ad15 )**: [Flight] Allow lazily resolving outlined models ([#28780](react/react#28780)) //<Sebastian Markbåge>//
- **[4c12339](react/react@4c12339ce )**: [DOM] move `flushSync` out of the reconciler ([#28500](react/react#28500)) //<Josh Story>//
- **[8e1462e](react/react@8e1462e8c )**: [Fiber] Move updatePriority tracking to renderers ([#28751](react/react#28751)) //<Josh Story>//
- **[0b3b8a6](react/react@0b3b8a6a3 )**: jsx: Remove unnecessary hasOwnProperty check ([#28775](react/react#28775)) //<Andrew Clark>//
- **[2acfb7b](react/react@2acfb7b60 )**: [Flight] Support FormData from Server to Client ([#28754](react/react#28754)) //<Sebastian Markbåge>//
- **[d1547de](react/react@d1547defe )**: Fast JSX: Don't clone props object ([#28768](react/react#28768)) //<Andrew Clark>//
- **[bfd8da8](react/react@bfd8da807 )**: Make class prop resolution faster ([#28766](react/react#28766)) //<Andrew Clark>//
- **[cbb6f2b](react/react@cbb6f2b54 )**: [Flight] Support Blobs from Server to Client ([#28755](react/react#28755)) //<Sebastian Markbåge>//
- **[f33a6b6](react/react@f33a6b69c )**: Track Owner for Server Components in DEV ([#28753](react/react#28753)) //<Sebastian Markbåge>//
- **[e3ebcd5](react/react@e3ebcd54b )**: Move string ref coercion to JSX runtime ([#28473](react/react#28473)) //<Andrew Clark>//
- **[fd0da3e](react/react@fd0da3eef )**: Remove _owner field from JSX elements in prod if string refs are disabled ([#28739](react/react#28739)) //<Sebastian Markbåge>//
Changelog:
[General][Changed] - React Native sync for revisions 48b4ecc...b5e5ce8
jest_e2e[run_all_tests]
bypass-github-export-checks
Reviewed By: kassens
Differential Revision: D56251607
fbshipit-source-id: e16db2fa101fc7ed1e009158c76388206beabd5f
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA SignedReact Core TeamOpened by a member of the React Core Team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@acdlite@react-sizebot@sebmarkbage@gnoff@facebook-github-bot
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Automatically reset forms after action finishes - #28804

Merged
acdlite merged 1 commit into
react:mainfrom
acdlite:automatically-reset-forms
Apr 10, 2024
Merged

Automatically reset forms after action finishes#28804
acdlite merged 1 commit into
react:mainfrom
acdlite:automatically-reset-forms

Conversation

@acdlite

Copy link
Copy Markdown
Collaborator

This updates the behavior of form actions to automatically reset the form's uncontrolled inputs after the action finishes.

This is a frequent feature request for people using actions and it aligns the behavior of client-side form submissions more closely with MPA form submissions.

It has no impact on controlled form inputs. It's the same as if you called form.reset() manually, except React handles the timing of when the reset happens, which is tricky/impossible to get exactly right in userspace.

The reset shouldn't happen until the UI has updated with the result of the action. So, resetting inside the action is too early.

Resetting in useEffect is better, but it's later than ideal because any effects that run before it will observe the state of the form before it's been reset.

It needs to happen in the mutation phase of the transition. More specifically, after all the DOM mutations caused by the transition have been applied. That way the defaultValue of the inputs are updated before the values are reset. The idea is that the defaultValue represents the current, canonical value sent by the server.

Note: this change has no effect on form submissions that aren't triggered by an action.

@facebook-github-botfacebook-github-bot added CLA Signed React Core Team Opened by a member of the React Core Team labels Apr 10, 2024
@react-sizebot

react-sizebot commented Apr 10, 2024

Copy link
Copy Markdown

Comparing: ed3c65c...562f9c9

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name+/-BaseCurrent+/- gzipBase gzipCurrent gzip
oss-stable/react-dom/cjs/react-dom.production.min.js+0.27%168.12 kB168.57 kB+0.24%52.72 kB52.85 kB
oss-experimental/react-dom/cjs/react-dom.production.min.js+0.26%169.92 kB170.37 kB+0.20%53.26 kB53.37 kB
facebook-www/ReactDOM-prod.classic.js+0.22%589.57 kB590.89 kB+0.22%103.80 kB104.03 kB
facebook-www/ReactDOM-prod.modern.js+0.23%565.41 kB566.73 kB+0.23%99.93 kB100.16 kB
test_utils/ReactAllWarnings.jsDeleted64.24 kB0.00 kBDeleted16.03 kB0.00 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name+/-BaseCurrent+/- gzipBase gzipCurrent gzip
oss-stable-semver/react-reconciler/cjs/react-reconciler.production.js+0.49%665.84 kB669.08 kB+0.51%146.23 kB146.97 kB
oss-stable/react-reconciler/cjs/react-reconciler.production.js+0.49%665.86 kB669.11 kB+0.51%146.26 kB147.01 kB
oss-experimental/react-reconciler/cjs/react-reconciler.production.js+0.48%672.88 kB676.12 kB+0.53%147.79 kB148.57 kB
oss-stable-semver/react-reconciler/cjs/react-reconciler.development.js+0.48%908.86 kB913.24 kB+0.53%195.30 kB196.34 kB
oss-stable/react-reconciler/cjs/react-reconciler.development.js+0.48%908.89 kB913.27 kB+0.53%195.33 kB196.37 kB
oss-experimental/react-reconciler/cjs/react-reconciler.development.js+0.48%918.20 kB922.58 kB+0.53%197.14 kB198.19 kB
oss-stable-semver/react-reconciler/cjs/react-reconciler.profiling.js+0.46%705.86 kB709.10 kB+0.50%153.52 kB154.29 kB
oss-stable/react-reconciler/cjs/react-reconciler.profiling.js+0.46%705.89 kB709.13 kB+0.50%153.55 kB154.31 kB
oss-experimental/react-reconciler/cjs/react-reconciler.profiling.js+0.46%712.90 kB716.14 kB+0.49%155.11 kB155.88 kB
oss-stable-semver/react-reconciler/cjs/react-reconciler.production.min.js+0.43%108.56 kB109.03 kB+0.39%33.85 kB33.98 kB
oss-stable/react-reconciler/cjs/react-reconciler.production.min.js+0.43%108.59 kB109.06 kB+0.39%33.87 kB34.00 kB
oss-experimental/react-reconciler/cjs/react-reconciler.production.min.js+0.42%110.35 kB110.82 kB+0.37%34.47 kB34.60 kB
oss-stable-semver/react-reconciler/cjs/react-reconciler.profiling.min.js+0.40%117.42 kB117.89 kB+0.32%36.09 kB36.21 kB
oss-stable/react-reconciler/cjs/react-reconciler.profiling.min.js+0.40%117.45 kB117.92 kB+0.33%36.11 kB36.23 kB
oss-experimental/react-reconciler/cjs/react-reconciler.profiling.min.js+0.39%119.21 kB119.67 kB+0.41%36.65 kB36.80 kB
oss-stable-semver/react-dom/cjs/react-dom.production.js+0.35%919.85 kB923.06 kB+0.37%206.89 kB207.65 kB
oss-stable/react-dom/cjs/react-dom.production.js+0.35%919.87 kB923.08 kB+0.37%206.92 kB207.68 kB
oss-experimental/react-dom/cjs/react-dom.production.js+0.35%926.94 kB930.15 kB+0.37%208.43 kB209.20 kB
oss-experimental/react-dom/cjs/react-dom-unstable_testing.production.js+0.34%945.18 kB948.39 kB+0.36%212.95 kB213.71 kB
oss-stable-semver/react-dom/cjs/react-dom.development.js+0.34%1,293.34 kB1,297.68 kB+0.37%286.49 kB287.55 kB
oss-stable/react-dom/cjs/react-dom.development.js+0.34%1,293.36 kB1,297.71 kB+0.37%286.52 kB287.58 kB
oss-stable-semver/react-dom/umd/react-dom.development.js+0.34%1,356.09 kB1,360.63 kB+0.38%289.40 kB290.49 kB
oss-stable/react-dom/umd/react-dom.development.js+0.34%1,356.12 kB1,360.66 kB+0.38%289.43 kB290.52 kB
oss-stable-semver/react-dom/cjs/react-dom.profiling.js+0.33%960.46 kB963.67 kB+0.35%214.16 kB214.92 kB
oss-stable/react-dom/cjs/react-dom.profiling.js+0.33%960.48 kB963.69 kB+0.35%214.19 kB214.95 kB
oss-experimental/react-dom/cjs/react-dom.development.js+0.33%1,302.73 kB1,307.08 kB+0.37%288.32 kB289.39 kB
oss-experimental/react-dom/umd/react-dom.development.js+0.33%1,365.97 kB1,370.51 kB+0.36%291.21 kB292.26 kB
oss-experimental/react-dom/cjs/react-dom.profiling.js+0.33%967.55 kB970.76 kB+0.35%215.71 kB216.46 kB
oss-experimental/react-dom/cjs/react-dom-unstable_testing.development.js+0.33%1,321.15 kB1,325.50 kB+0.37%292.77 kB293.84 kB
facebook-www/ReactDOM-dev.modern.js+0.30%1,621.20 kB1,626.01 kB+0.34%322.53 kB323.63 kB
facebook-www/ReactDOMTesting-dev.modern.js+0.29%1,644.60 kB1,649.41 kB+0.34%327.14 kB328.26 kB
facebook-www/ReactDOM-dev.classic.js+0.29%1,673.24 kB1,678.05 kB+0.34%331.38 kB332.50 kB
facebook-www/ReactDOMTesting-dev.classic.js+0.28%1,697.92 kB1,702.73 kB+0.33%336.19 kB337.31 kB
oss-stable-semver/react-dom/umd/react-dom.production.min.js+0.27%167.79 kB168.24 kB+0.28%53.04 kB53.19 kB
oss-stable/react-dom/umd/react-dom.production.min.js+0.27%167.87 kB168.32 kB+0.28%53.07 kB53.22 kB
oss-stable-semver/react-dom/cjs/react-dom.production.min.js+0.27%168.04 kB168.49 kB+0.24%52.69 kB52.82 kB
oss-stable/react-dom/cjs/react-dom.production.min.js+0.27%168.12 kB168.57 kB+0.24%52.72 kB52.85 kB
oss-experimental/react-dom/umd/react-dom.production.min.js+0.27%169.67 kB170.13 kB+0.25%53.70 kB53.83 kB
oss-experimental/react-dom/cjs/react-dom.production.min.js+0.26%169.92 kB170.37 kB+0.20%53.26 kB53.37 kB
oss-stable-semver/react-dom/umd/react-dom.profiling.min.js+0.25%176.63 kB177.08 kB+0.21%55.45 kB55.56 kB
oss-stable/react-dom/umd/react-dom.profiling.min.js+0.25%176.71 kB177.16 kB+0.21%55.47 kB55.59 kB
oss-experimental/react-dom/cjs/react-dom-unstable_testing.production.min.js+0.25%176.86 kB177.31 kB+0.20%55.85 kB55.97 kB
oss-stable-semver/react-dom/cjs/react-dom.profiling.min.js+0.25%177.32 kB177.77 kB+0.22%55.14 kB55.26 kB
oss-stable/react-dom/cjs/react-dom.profiling.min.js+0.25%177.40 kB177.85 kB+0.22%55.16 kB55.28 kB
oss-experimental/react-dom/umd/react-dom.profiling.min.js+0.25%178.51 kB178.96 kB+0.25%56.01 kB56.15 kB
oss-experimental/react-dom/cjs/react-dom.profiling.min.js+0.25%179.21 kB179.66 kB+0.25%55.71 kB55.85 kB
facebook-www/ReactDOM-prod.modern.js+0.23%565.41 kB566.73 kB+0.23%99.93 kB100.16 kB
facebook-www/ReactDOMTesting-prod.modern.js+0.23%581.36 kB582.67 kB+0.22%103.88 kB104.11 kB
facebook-www/ReactDOM-prod.classic.js+0.22%589.57 kB590.89 kB+0.22%103.80 kB104.03 kB
facebook-www/ReactDOM-profiling.modern.js+0.22%594.31 kB595.63 kB+0.22%104.07 kB104.29 kB
facebook-www/ReactDOMTesting-prod.classic.js+0.22%604.22 kB605.54 kB+0.21%107.51 kB107.74 kB
facebook-www/ReactDOM-profiling.classic.js+0.21%619.11 kB620.43 kB+0.22%108.10 kB108.33 kB
test_utils/ReactAllWarnings.jsDeleted64.24 kB0.00 kBDeleted16.03 kB0.00 kB

Generated by 🚫 dangerJS against 562f9c9

@acdlite
acdliteforce-pushed the automatically-reset-forms branch 2 times, most recently from 5e8fad4 to 41e6173CompareApril 10, 2024 00:38
@acdlite
acdlite marked this pull request as ready for review April 10, 2024 00:41

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should start a campaign for javascript64

@acdliteacdlite mentioned this pull request Apr 10, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right
in userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
@acdlite
acdliteforce-pushed the automatically-reset-forms branch from 41e6173 to 562f9c9CompareApril 10, 2024 04:04
const newResetState = {};
const resetStateHook: Hook = (formFiber.memoizedState.next: any);
const resetStateQueue = resetStateHook.queue;
dispatchSetState(formFiber, resetStateQueue, newResetState);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this actually have to be on the Fiber?

Can't it just be scheduled on the Root with a list of forms to reset when the root commits?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That way you don't need all the special commit phase stuff.

@acdliteacdliteApr 10, 2024

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm I'll need to think more about that, the scenario I had in mind was if the form is inside a Suspense boundary, the root could commit before the input's defaultValue had been updated. Usually this shouldn't happen because during a Transition we won't hide already visible forms, but during a popstate transition we might.

The <input form="myform"> case is interesting there, too.

@acdlite
acdlite merged commit 41950d1 into react:mainApr 10, 2024
acdlite added a commit that referenced this pull request Apr 10, 2024
Based on:
- #28804 ---
This sets adds a new ReactDOM export called requestFormReset, including
setting up the export and creating a method on the internal ReactDOM
dispatcher. It does not yet add any implementation.
Doing this in its own commit for review purposes.
The API itself will be explained in the next PR.
acdlite added a commit that referenced this pull request Apr 10, 2024
Based on:
- #28808
- #28804 ---
This adds a React DOM method called requestFormReset that schedules a
form reset to occur when the current transition completes.
Internally, it's the same method that's called automatically whenever a
form action is submitted. It only affects uncontrolled form inputs. See
#28804 for details.
The reason for the public API is so UI libraries can implement their own
action-based APIs and maintain the form-resetting behavior, something
like this:
```js
function onSubmit(event) {
// Disable default form submission behavior
event.preventDefault();
const form = event.target;
startTransition(async () => {
// Request the form to reset once the action
// has completed
requestFormReset(form);
// Call the user-provided action prop
await action(new FormData(form));
})
}
```
github-actionsBot pushed a commit that referenced this pull request Apr 10, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right in
userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
DiffTrain build for [41950d1](41950d1)
github-actionsBot pushed a commit that referenced this pull request Apr 10, 2024
Based on:
- #28804
---
This sets adds a new ReactDOM export called requestFormReset, including
setting up the export and creating a method on the internal ReactDOM
dispatcher. It does not yet add any implementation.
Doing this in its own commit for review purposes.
The API itself will be explained in the next PR.
DiffTrain build for [374b5d2](374b5d2)
github-actionsBot pushed a commit that referenced this pull request Apr 10, 2024
Based on:
- #28808
- #28804
---
This adds a React DOM method called requestFormReset that schedules a
form reset to occur when the current transition completes.
Internally, it's the same method that's called automatically whenever a
form action is submitted. It only affects uncontrolled form inputs. See
#28804 for details.
The reason for the public API is so UI libraries can implement their own
action-based APIs and maintain the form-resetting behavior, something
like this:
```js
function onSubmit(event) {
// Disable default form submission behavior
event.preventDefault();
const form = event.target;
startTransition(async () => {
// Request the form to reset once the action
// has completed
requestFormReset(form);
// Call the user-provided action prop
await action(new FormData(form));
})
}
```
DiffTrain build for [da69b6a](da69b6a)
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right in
userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
Based on:
- #28804 ---
This sets adds a new ReactDOM export called requestFormReset, including
setting up the export and creating a method on the internal ReactDOM
dispatcher. It does not yet add any implementation.
Doing this in its own commit for review purposes.
The API itself will be explained in the next PR.
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
Based on:
- #28808
- #28804 ---
This adds a React DOM method called requestFormReset that schedules a
form reset to occur when the current transition completes.
Internally, it's the same method that's called automatically whenever a
form action is submitted. It only affects uncontrolled form inputs. See
#28804 for details.
The reason for the public API is so UI libraries can implement their own
action-based APIs and maintain the form-resetting behavior, something
like this:
```js
function onSubmit(event) {
// Disable default form submission behavior
event.preventDefault();
const form = event.target;
startTransition(async () => {
// Request the form to reset once the action
// has completed
requestFormReset(form);
// Call the user-provided action prop
await action(new FormData(form));
})
}
```
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right in
userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
Based on:
- #28804 ---
This sets adds a new ReactDOM export called requestFormReset, including
setting up the export and creating a method on the internal ReactDOM
dispatcher. It does not yet add any implementation.
Doing this in its own commit for review purposes.
The API itself will be explained in the next PR.
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
Based on:
- #28808
- #28804 ---
This adds a React DOM method called requestFormReset that schedules a
form reset to occur when the current transition completes.
Internally, it's the same method that's called automatically whenever a
form action is submitted. It only affects uncontrolled form inputs. See
#28804 for details.
The reason for the public API is so UI libraries can implement their own
action-based APIs and maintain the form-resetting behavior, something
like this:
```js
function onSubmit(event) {
// Disable default form submission behavior
event.preventDefault();
const form = event.target;
startTransition(async () => {
// Request the form to reset once the action
// has completed
requestFormReset(form);
// Call the user-provided action prop
await action(new FormData(form));
})
}
```
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right in
userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
Based on:
- react#28804 ---
This sets adds a new ReactDOM export called requestFormReset, including
setting up the export and creating a method on the internal ReactDOM
dispatcher. It does not yet add any implementation.
Doing this in its own commit for review purposes.
The API itself will be explained in the next PR.
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
Based on:
- react#28808
- react#28804 ---
This adds a React DOM method called requestFormReset that schedules a
form reset to occur when the current transition completes.
Internally, it's the same method that's called automatically whenever a
form action is submitted. It only affects uncontrolled form inputs. See
react#28804 for details.
The reason for the public API is so UI libraries can implement their own
action-based APIs and maintain the form-resetting behavior, something
like this:
```js
function onSubmit(event) {
// Disable default form submission behavior
event.preventDefault();
const form = event.target;
startTransition(async () => {
// Request the form to reset once the action
// has completed
requestFormReset(form);
// Call the user-provided action prop
await action(new FormData(form));
})
}
```
bigfootjon pushed a commit that referenced this pull request Apr 18, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right in
userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
DiffTrain build for commit 41950d1.
facebook-github-bot pushed a commit to react/react-native that referenced this pull request Apr 19, 2024
Summary:
This sync includes the changes from:
- D56103750
- [TODO] A shim for SECRET_INTERNALS
This sync includes the following changes:
- **[b5e5ce8](react/react@b5e5ce8e0 )**: Update ReactNativeTypes for root options (part 2) ([#28857](react/react#28857)) //<Ricky>//
- **[da6ba53](react/react@da6ba53b1 )**: [UMD] Remove umd builds ([#28735](react/react#28735)) //<Josh Story>//
- **[0c245df](react/react@0c245df1d )**: Complete the typo fix ([#28856](react/react#28856)) //<Sebastian Silbermann>//
- **[f82051d](react/react@f82051d7a )**: console test utils fix: match entire string, not just first letter ([#28855](react/react#28855)) //<Andrew Clark>//
- **[4ca20fd](react/react@4ca20fd36 )**: Test top level fragment inside lazy semantics ([#28852](react/react#28852)) //<Sebastian Markbåge>//
- **[c0cf7c6](react/react@c0cf7c696 )**: Promote ASYNC_ITERATOR symbol to React Symbols ([#28851](react/react#28851)) //<Sebastian Markbåge>//
- **[657428a](react/react@657428a9e )**: Add ReactNativeTypes for root options ([#28850](react/react#28850)) //<Ricky>//
- **[7909d8e](react/react@7909d8eab )**: [Flight] Encode ReadableStream and AsyncIterables ([#28847](react/react#28847)) //<Sebastian Markbåge>//
- **[13eb61d](react/react@13eb61d05 )**: Move enableUseDeferredValueInitialArg to canary ([#28818](react/react#28818)) //<Andrew Clark>//
- **[8afa144](react/react@8afa144bd )**: Enable flag disableClientCache ([#28846](react/react#28846)) //<Jan Kassens>//
- **[734956a](react/react@734956ace )**: Devtools: Add support for useFormStatus ([#28413](react/react#28413)) //<Sebastian Silbermann>//
- **[17e920c](react/react@17e920c00 )**: [Flight Reply] Encode Typed Arrays and Blobs ([#28819](react/react#28819)) //<Sebastian Markbåge>//
- **[0347fcd](react/react@0347fcd00 )**: Add on(Caught|Uncaught|Recoverable) opts to RN ([#28836](react/react#28836)) //<Ricky>//
- **[c113503](react/react@c113503ad )**: Flush direct streams in Bun ([#28837](react/react#28837)) //<Kenta Iwasaki>//
- **[9defcd5](react/react@9defcd56b )**: Remove redundant props assign ([#28829](react/react#28829)) //<Sebastian Silbermann>//
- **[ed40236](react/react@ed4023603 )**: Fix mistaken "react-server" condition ([#28835](react/react#28835)) //<Sebastian Markbåge>//
- **[c8a0350](react/react@c8a035036 )**: [Fizz] hoistables should never flush before the preamble ([#28802](react/react#28802)) //<Josh Story>//
- **[4f5c812](react/react@4f5c812a3 )**: DevTools: Rely on sourcemaps to compute hook name of built-in hooks in newer versions ([#28593](react/react#28593)) //<Sebastian Silbermann>//
- **[4354159](react/react@435415962 )**: Backwards compatibility for string refs on WWW ([#28826](react/react#28826)) //<Jack Pope>//
- **[608edcc](react/react@608edcc90 )**: [tests] add `assertConsole<method>Dev` helpers ([#28732](react/react#28732)) //<Ricky>//
- **[da69b6a](react/react@da69b6af9 )**: ReactDOM.requestFormReset ([#28809](react/react#28809)) //<Andrew Clark>//
- **[374b5d2](react/react@374b5d26c )**: Scaffolding for requestFormReset API ([#28808](react/react#28808)) //<Andrew Clark>//
- **[41950d1](react/react@41950d14a )**: Automatically reset forms after action finishes ([#28804](react/react#28804)) //<Andrew Clark>//
- **[dc6a7e0](react/react@dc6a7e01e )**: [Float] Don't preload images inside `<noscript>` ([#28815](react/react#28815)) //<Josh Story>//
- **[3f947b1](react/react@3f947b1b4 )**: [tests] Assert scheduler log empty in internalAct ([#28737](react/react#28737)) //<Ricky>//
- **[bf09089](react/react@bf09089f6 )**: Remove Scheduler.log from ReactSuspenseFuzz-test ([#28812](react/react#28812)) //<Ricky>//
- **[84cb3b4](react/react@84cb3b4cb )**: Hardcode disableIEWorkarounds for www ([#28811](react/react#28811)) //<Ricky>//
- **[2243b40](react/react@2243b40ab )**: [tests] assertLog before act in useEffectEvent ([#28763](react/react#28763)) //<Ricky>//
- **[dfc64c6](react/react@dfc64c6e3 )**: [tests] assertLog before act in ReactUse ([#28762](react/react#28762)) //<Ricky>//
- **[42eff4b](react/react@42eff4bc7 )**: [tests] Fix assertions not flushed before act ([#28745](react/react#28745)) //<Ricky>//
- **[ed3c65c](react/react@ed3c65caf )**: Warn if outdated JSX transform is detected ([#28781](react/react#28781)) //<Andrew Clark>//
- **[3f9e237](react/react@3f9e237a2 )**: Fix: Suspend while recovering from hydration error ([#28800](react/react#28800)) //<Andrew Clark>//
- **[7f5d25e](react/react@7f5d25e23 )**: Fix cloneElement using string ref w no owner ([#28797](react/react#28797)) //<Joseph Savona>//
- **[bf40b02](react/react@bf40b0244 )**: [Fizz] Stop publishing external-runtime to stable channel ([#28796](react/react#28796)) //<Josh Story>//
- **[7f93cb4](react/react@7f93cb41c )**: [DOM] Infer react-server entries bundles if not explicitly configured ([#28795](react/react#28795)) //<Josh Story>//
- **[f613165](react/react@f61316535 )**: Rename SECRET INTERNALS to `__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE` ([#28789](react/react#28789)) //<Sebastian Markbåge>//
- **[9644d20](react/react@9644d206e )**: Soften useFormState warning ([#28788](react/react#28788)) //<Ricky>//
- **[c771016](react/react@c771016e1 )**: Rename The Secret Export of Server Internals ([#28786](react/react#28786)) //<Sebastian Markbåge>//
- **[d50323e](react/react@d50323eb8 )**: Flatten ReactSharedInternals ([#28783](react/react#28783)) //<Sebastian Markbåge>//
- **[f62cf8c](react/react@f62cf8c62 )**: [Float] treat `props.async` in Float consistent with the rest of react-dom ([#26760](react/react#26760)) //<Josh Story>//
- **[dfd3d5a](react/react@dfd3d5af8 )**: Add support for transition{run,start,cancel} events ([#27345](react/react#27345)) //<Hugo Sales>//
- **[1f8327f](react/react@1f8327f83 )**: [Fiber] Use real event priority for hydration scheduling ([#28765](react/react#28765)) //<Josh Story>//
- **[97c90ed](react/react@97c90ed88 )**: [DOM] Shrink ReactDOMCurrentDispatcher method names ([#28770](react/react#28770)) //<Josh Story>//
- **[9007fdc](react/react@9007fdc8f )**: [DOM] Shrink ReactDOMSharedInternals source representation ([#28771](react/react#28771)) //<Josh Story>//
- **[14f50ad](react/react@14f50ad15 )**: [Flight] Allow lazily resolving outlined models ([#28780](react/react#28780)) //<Sebastian Markbåge>//
- **[4c12339](react/react@4c12339ce )**: [DOM] move `flushSync` out of the reconciler ([#28500](react/react#28500)) //<Josh Story>//
- **[8e1462e](react/react@8e1462e8c )**: [Fiber] Move updatePriority tracking to renderers ([#28751](react/react#28751)) //<Josh Story>//
- **[0b3b8a6](react/react@0b3b8a6a3 )**: jsx: Remove unnecessary hasOwnProperty check ([#28775](react/react#28775)) //<Andrew Clark>//
- **[2acfb7b](react/react@2acfb7b60 )**: [Flight] Support FormData from Server to Client ([#28754](react/react#28754)) //<Sebastian Markbåge>//
- **[d1547de](react/react@d1547defe )**: Fast JSX: Don't clone props object ([#28768](react/react#28768)) //<Andrew Clark>//
- **[bfd8da8](react/react@bfd8da807 )**: Make class prop resolution faster ([#28766](react/react#28766)) //<Andrew Clark>//
- **[cbb6f2b](react/react@cbb6f2b54 )**: [Flight] Support Blobs from Server to Client ([#28755](react/react#28755)) //<Sebastian Markbåge>//
- **[f33a6b6](react/react@f33a6b69c )**: Track Owner for Server Components in DEV ([#28753](react/react#28753)) //<Sebastian Markbåge>//
- **[e3ebcd5](react/react@e3ebcd54b )**: Move string ref coercion to JSX runtime ([#28473](react/react#28473)) //<Andrew Clark>//
- **[fd0da3e](react/react@fd0da3eef )**: Remove _owner field from JSX elements in prod if string refs are disabled ([#28739](react/react#28739)) //<Sebastian Markbåge>//
Changelog:
[General][Changed] - React Native sync for revisions 48b4ecc...b5e5ce8
jest_e2e[run_all_tests]
bypass-github-export-checks
Reviewed By: kassens
Differential Revision: D56251607
fbshipit-source-id: e16db2fa101fc7ed1e009158c76388206beabd5f
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA SignedReact Core TeamOpened by a member of the React Core Team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@acdlite@react-sizebot@sebmarkbage@gnoff@facebook-github-bot
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Automatically reset forms after action finishes - #28804

Merged
acdlite merged 1 commit into
react:mainfrom
acdlite:automatically-reset-forms
Apr 10, 2024
Merged

Automatically reset forms after action finishes#28804
acdlite merged 1 commit into
react:mainfrom
acdlite:automatically-reset-forms

Conversation

@acdlite

Copy link
Copy Markdown
Collaborator

This updates the behavior of form actions to automatically reset the form's uncontrolled inputs after the action finishes.

This is a frequent feature request for people using actions and it aligns the behavior of client-side form submissions more closely with MPA form submissions.

It has no impact on controlled form inputs. It's the same as if you called form.reset() manually, except React handles the timing of when the reset happens, which is tricky/impossible to get exactly right in userspace.

The reset shouldn't happen until the UI has updated with the result of the action. So, resetting inside the action is too early.

Resetting in useEffect is better, but it's later than ideal because any effects that run before it will observe the state of the form before it's been reset.

It needs to happen in the mutation phase of the transition. More specifically, after all the DOM mutations caused by the transition have been applied. That way the defaultValue of the inputs are updated before the values are reset. The idea is that the defaultValue represents the current, canonical value sent by the server.

Note: this change has no effect on form submissions that aren't triggered by an action.

@facebook-github-botfacebook-github-bot added CLA Signed React Core Team Opened by a member of the React Core Team labels Apr 10, 2024
@react-sizebot

react-sizebot commented Apr 10, 2024

Copy link
Copy Markdown

Comparing: ed3c65c...562f9c9

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name+/-BaseCurrent+/- gzipBase gzipCurrent gzip
oss-stable/react-dom/cjs/react-dom.production.min.js+0.27%168.12 kB168.57 kB+0.24%52.72 kB52.85 kB
oss-experimental/react-dom/cjs/react-dom.production.min.js+0.26%169.92 kB170.37 kB+0.20%53.26 kB53.37 kB
facebook-www/ReactDOM-prod.classic.js+0.22%589.57 kB590.89 kB+0.22%103.80 kB104.03 kB
facebook-www/ReactDOM-prod.modern.js+0.23%565.41 kB566.73 kB+0.23%99.93 kB100.16 kB
test_utils/ReactAllWarnings.jsDeleted64.24 kB0.00 kBDeleted16.03 kB0.00 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name+/-BaseCurrent+/- gzipBase gzipCurrent gzip
oss-stable-semver/react-reconciler/cjs/react-reconciler.production.js+0.49%665.84 kB669.08 kB+0.51%146.23 kB146.97 kB
oss-stable/react-reconciler/cjs/react-reconciler.production.js+0.49%665.86 kB669.11 kB+0.51%146.26 kB147.01 kB
oss-experimental/react-reconciler/cjs/react-reconciler.production.js+0.48%672.88 kB676.12 kB+0.53%147.79 kB148.57 kB
oss-stable-semver/react-reconciler/cjs/react-reconciler.development.js+0.48%908.86 kB913.24 kB+0.53%195.30 kB196.34 kB
oss-stable/react-reconciler/cjs/react-reconciler.development.js+0.48%908.89 kB913.27 kB+0.53%195.33 kB196.37 kB
oss-experimental/react-reconciler/cjs/react-reconciler.development.js+0.48%918.20 kB922.58 kB+0.53%197.14 kB198.19 kB
oss-stable-semver/react-reconciler/cjs/react-reconciler.profiling.js+0.46%705.86 kB709.10 kB+0.50%153.52 kB154.29 kB
oss-stable/react-reconciler/cjs/react-reconciler.profiling.js+0.46%705.89 kB709.13 kB+0.50%153.55 kB154.31 kB
oss-experimental/react-reconciler/cjs/react-reconciler.profiling.js+0.46%712.90 kB716.14 kB+0.49%155.11 kB155.88 kB
oss-stable-semver/react-reconciler/cjs/react-reconciler.production.min.js+0.43%108.56 kB109.03 kB+0.39%33.85 kB33.98 kB
oss-stable/react-reconciler/cjs/react-reconciler.production.min.js+0.43%108.59 kB109.06 kB+0.39%33.87 kB34.00 kB
oss-experimental/react-reconciler/cjs/react-reconciler.production.min.js+0.42%110.35 kB110.82 kB+0.37%34.47 kB34.60 kB
oss-stable-semver/react-reconciler/cjs/react-reconciler.profiling.min.js+0.40%117.42 kB117.89 kB+0.32%36.09 kB36.21 kB
oss-stable/react-reconciler/cjs/react-reconciler.profiling.min.js+0.40%117.45 kB117.92 kB+0.33%36.11 kB36.23 kB
oss-experimental/react-reconciler/cjs/react-reconciler.profiling.min.js+0.39%119.21 kB119.67 kB+0.41%36.65 kB36.80 kB
oss-stable-semver/react-dom/cjs/react-dom.production.js+0.35%919.85 kB923.06 kB+0.37%206.89 kB207.65 kB
oss-stable/react-dom/cjs/react-dom.production.js+0.35%919.87 kB923.08 kB+0.37%206.92 kB207.68 kB
oss-experimental/react-dom/cjs/react-dom.production.js+0.35%926.94 kB930.15 kB+0.37%208.43 kB209.20 kB
oss-experimental/react-dom/cjs/react-dom-unstable_testing.production.js+0.34%945.18 kB948.39 kB+0.36%212.95 kB213.71 kB
oss-stable-semver/react-dom/cjs/react-dom.development.js+0.34%1,293.34 kB1,297.68 kB+0.37%286.49 kB287.55 kB
oss-stable/react-dom/cjs/react-dom.development.js+0.34%1,293.36 kB1,297.71 kB+0.37%286.52 kB287.58 kB
oss-stable-semver/react-dom/umd/react-dom.development.js+0.34%1,356.09 kB1,360.63 kB+0.38%289.40 kB290.49 kB
oss-stable/react-dom/umd/react-dom.development.js+0.34%1,356.12 kB1,360.66 kB+0.38%289.43 kB290.52 kB
oss-stable-semver/react-dom/cjs/react-dom.profiling.js+0.33%960.46 kB963.67 kB+0.35%214.16 kB214.92 kB
oss-stable/react-dom/cjs/react-dom.profiling.js+0.33%960.48 kB963.69 kB+0.35%214.19 kB214.95 kB
oss-experimental/react-dom/cjs/react-dom.development.js+0.33%1,302.73 kB1,307.08 kB+0.37%288.32 kB289.39 kB
oss-experimental/react-dom/umd/react-dom.development.js+0.33%1,365.97 kB1,370.51 kB+0.36%291.21 kB292.26 kB
oss-experimental/react-dom/cjs/react-dom.profiling.js+0.33%967.55 kB970.76 kB+0.35%215.71 kB216.46 kB
oss-experimental/react-dom/cjs/react-dom-unstable_testing.development.js+0.33%1,321.15 kB1,325.50 kB+0.37%292.77 kB293.84 kB
facebook-www/ReactDOM-dev.modern.js+0.30%1,621.20 kB1,626.01 kB+0.34%322.53 kB323.63 kB
facebook-www/ReactDOMTesting-dev.modern.js+0.29%1,644.60 kB1,649.41 kB+0.34%327.14 kB328.26 kB
facebook-www/ReactDOM-dev.classic.js+0.29%1,673.24 kB1,678.05 kB+0.34%331.38 kB332.50 kB
facebook-www/ReactDOMTesting-dev.classic.js+0.28%1,697.92 kB1,702.73 kB+0.33%336.19 kB337.31 kB
oss-stable-semver/react-dom/umd/react-dom.production.min.js+0.27%167.79 kB168.24 kB+0.28%53.04 kB53.19 kB
oss-stable/react-dom/umd/react-dom.production.min.js+0.27%167.87 kB168.32 kB+0.28%53.07 kB53.22 kB
oss-stable-semver/react-dom/cjs/react-dom.production.min.js+0.27%168.04 kB168.49 kB+0.24%52.69 kB52.82 kB
oss-stable/react-dom/cjs/react-dom.production.min.js+0.27%168.12 kB168.57 kB+0.24%52.72 kB52.85 kB
oss-experimental/react-dom/umd/react-dom.production.min.js+0.27%169.67 kB170.13 kB+0.25%53.70 kB53.83 kB
oss-experimental/react-dom/cjs/react-dom.production.min.js+0.26%169.92 kB170.37 kB+0.20%53.26 kB53.37 kB
oss-stable-semver/react-dom/umd/react-dom.profiling.min.js+0.25%176.63 kB177.08 kB+0.21%55.45 kB55.56 kB
oss-stable/react-dom/umd/react-dom.profiling.min.js+0.25%176.71 kB177.16 kB+0.21%55.47 kB55.59 kB
oss-experimental/react-dom/cjs/react-dom-unstable_testing.production.min.js+0.25%176.86 kB177.31 kB+0.20%55.85 kB55.97 kB
oss-stable-semver/react-dom/cjs/react-dom.profiling.min.js+0.25%177.32 kB177.77 kB+0.22%55.14 kB55.26 kB
oss-stable/react-dom/cjs/react-dom.profiling.min.js+0.25%177.40 kB177.85 kB+0.22%55.16 kB55.28 kB
oss-experimental/react-dom/umd/react-dom.profiling.min.js+0.25%178.51 kB178.96 kB+0.25%56.01 kB56.15 kB
oss-experimental/react-dom/cjs/react-dom.profiling.min.js+0.25%179.21 kB179.66 kB+0.25%55.71 kB55.85 kB
facebook-www/ReactDOM-prod.modern.js+0.23%565.41 kB566.73 kB+0.23%99.93 kB100.16 kB
facebook-www/ReactDOMTesting-prod.modern.js+0.23%581.36 kB582.67 kB+0.22%103.88 kB104.11 kB
facebook-www/ReactDOM-prod.classic.js+0.22%589.57 kB590.89 kB+0.22%103.80 kB104.03 kB
facebook-www/ReactDOM-profiling.modern.js+0.22%594.31 kB595.63 kB+0.22%104.07 kB104.29 kB
facebook-www/ReactDOMTesting-prod.classic.js+0.22%604.22 kB605.54 kB+0.21%107.51 kB107.74 kB
facebook-www/ReactDOM-profiling.classic.js+0.21%619.11 kB620.43 kB+0.22%108.10 kB108.33 kB
test_utils/ReactAllWarnings.jsDeleted64.24 kB0.00 kBDeleted16.03 kB0.00 kB

Generated by 🚫 dangerJS against 562f9c9

@acdlite
acdliteforce-pushed the automatically-reset-forms branch 2 times, most recently from 5e8fad4 to 41e6173CompareApril 10, 2024 00:38
@acdlite
acdlite marked this pull request as ready for review April 10, 2024 00:41

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should start a campaign for javascript64

@acdliteacdlite mentioned this pull request Apr 10, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right
in userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
@acdlite
acdliteforce-pushed the automatically-reset-forms branch from 41e6173 to 562f9c9CompareApril 10, 2024 04:04
const newResetState = {};
const resetStateHook: Hook = (formFiber.memoizedState.next: any);
const resetStateQueue = resetStateHook.queue;
dispatchSetState(formFiber, resetStateQueue, newResetState);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this actually have to be on the Fiber?

Can't it just be scheduled on the Root with a list of forms to reset when the root commits?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That way you don't need all the special commit phase stuff.

@acdliteacdliteApr 10, 2024

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm I'll need to think more about that, the scenario I had in mind was if the form is inside a Suspense boundary, the root could commit before the input's defaultValue had been updated. Usually this shouldn't happen because during a Transition we won't hide already visible forms, but during a popstate transition we might.

The <input form="myform"> case is interesting there, too.

@acdlite
acdlite merged commit 41950d1 into react:mainApr 10, 2024
acdlite added a commit that referenced this pull request Apr 10, 2024
Based on:
- #28804 ---
This sets adds a new ReactDOM export called requestFormReset, including
setting up the export and creating a method on the internal ReactDOM
dispatcher. It does not yet add any implementation.
Doing this in its own commit for review purposes.
The API itself will be explained in the next PR.
acdlite added a commit that referenced this pull request Apr 10, 2024
Based on:
- #28808
- #28804 ---
This adds a React DOM method called requestFormReset that schedules a
form reset to occur when the current transition completes.
Internally, it's the same method that's called automatically whenever a
form action is submitted. It only affects uncontrolled form inputs. See
#28804 for details.
The reason for the public API is so UI libraries can implement their own
action-based APIs and maintain the form-resetting behavior, something
like this:
```js
function onSubmit(event) {
// Disable default form submission behavior
event.preventDefault();
const form = event.target;
startTransition(async () => {
// Request the form to reset once the action
// has completed
requestFormReset(form);
// Call the user-provided action prop
await action(new FormData(form));
})
}
```
github-actionsBot pushed a commit that referenced this pull request Apr 10, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right in
userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
DiffTrain build for [41950d1](41950d1)
github-actionsBot pushed a commit that referenced this pull request Apr 10, 2024
Based on:
- #28804
---
This sets adds a new ReactDOM export called requestFormReset, including
setting up the export and creating a method on the internal ReactDOM
dispatcher. It does not yet add any implementation.
Doing this in its own commit for review purposes.
The API itself will be explained in the next PR.
DiffTrain build for [374b5d2](374b5d2)
github-actionsBot pushed a commit that referenced this pull request Apr 10, 2024
Based on:
- #28808
- #28804
---
This adds a React DOM method called requestFormReset that schedules a
form reset to occur when the current transition completes.
Internally, it's the same method that's called automatically whenever a
form action is submitted. It only affects uncontrolled form inputs. See
#28804 for details.
The reason for the public API is so UI libraries can implement their own
action-based APIs and maintain the form-resetting behavior, something
like this:
```js
function onSubmit(event) {
// Disable default form submission behavior
event.preventDefault();
const form = event.target;
startTransition(async () => {
// Request the form to reset once the action
// has completed
requestFormReset(form);
// Call the user-provided action prop
await action(new FormData(form));
})
}
```
DiffTrain build for [da69b6a](da69b6a)
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right in
userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
Based on:
- #28804 ---
This sets adds a new ReactDOM export called requestFormReset, including
setting up the export and creating a method on the internal ReactDOM
dispatcher. It does not yet add any implementation.
Doing this in its own commit for review purposes.
The API itself will be explained in the next PR.
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
Based on:
- #28808
- #28804 ---
This adds a React DOM method called requestFormReset that schedules a
form reset to occur when the current transition completes.
Internally, it's the same method that's called automatically whenever a
form action is submitted. It only affects uncontrolled form inputs. See
#28804 for details.
The reason for the public API is so UI libraries can implement their own
action-based APIs and maintain the form-resetting behavior, something
like this:
```js
function onSubmit(event) {
// Disable default form submission behavior
event.preventDefault();
const form = event.target;
startTransition(async () => {
// Request the form to reset once the action
// has completed
requestFormReset(form);
// Call the user-provided action prop
await action(new FormData(form));
})
}
```
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right in
userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
Based on:
- #28804 ---
This sets adds a new ReactDOM export called requestFormReset, including
setting up the export and creating a method on the internal ReactDOM
dispatcher. It does not yet add any implementation.
Doing this in its own commit for review purposes.
The API itself will be explained in the next PR.
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
Based on:
- #28808
- #28804 ---
This adds a React DOM method called requestFormReset that schedules a
form reset to occur when the current transition completes.
Internally, it's the same method that's called automatically whenever a
form action is submitted. It only affects uncontrolled form inputs. See
#28804 for details.
The reason for the public API is so UI libraries can implement their own
action-based APIs and maintain the form-resetting behavior, something
like this:
```js
function onSubmit(event) {
// Disable default form submission behavior
event.preventDefault();
const form = event.target;
startTransition(async () => {
// Request the form to reset once the action
// has completed
requestFormReset(form);
// Call the user-provided action prop
await action(new FormData(form));
})
}
```
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right in
userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
Based on:
- react#28804 ---
This sets adds a new ReactDOM export called requestFormReset, including
setting up the export and creating a method on the internal ReactDOM
dispatcher. It does not yet add any implementation.
Doing this in its own commit for review purposes.
The API itself will be explained in the next PR.
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
Based on:
- react#28808
- react#28804 ---
This adds a React DOM method called requestFormReset that schedules a
form reset to occur when the current transition completes.
Internally, it's the same method that's called automatically whenever a
form action is submitted. It only affects uncontrolled form inputs. See
react#28804 for details.
The reason for the public API is so UI libraries can implement their own
action-based APIs and maintain the form-resetting behavior, something
like this:
```js
function onSubmit(event) {
// Disable default form submission behavior
event.preventDefault();
const form = event.target;
startTransition(async () => {
// Request the form to reset once the action
// has completed
requestFormReset(form);
// Call the user-provided action prop
await action(new FormData(form));
})
}
```
bigfootjon pushed a commit that referenced this pull request Apr 18, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right in
userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
DiffTrain build for commit 41950d1.
facebook-github-bot pushed a commit to react/react-native that referenced this pull request Apr 19, 2024
Summary:
This sync includes the changes from:
- D56103750
- [TODO] A shim for SECRET_INTERNALS
This sync includes the following changes:
- **[b5e5ce8](react/react@b5e5ce8e0 )**: Update ReactNativeTypes for root options (part 2) ([#28857](react/react#28857)) //<Ricky>//
- **[da6ba53](react/react@da6ba53b1 )**: [UMD] Remove umd builds ([#28735](react/react#28735)) //<Josh Story>//
- **[0c245df](react/react@0c245df1d )**: Complete the typo fix ([#28856](react/react#28856)) //<Sebastian Silbermann>//
- **[f82051d](react/react@f82051d7a )**: console test utils fix: match entire string, not just first letter ([#28855](react/react#28855)) //<Andrew Clark>//
- **[4ca20fd](react/react@4ca20fd36 )**: Test top level fragment inside lazy semantics ([#28852](react/react#28852)) //<Sebastian Markbåge>//
- **[c0cf7c6](react/react@c0cf7c696 )**: Promote ASYNC_ITERATOR symbol to React Symbols ([#28851](react/react#28851)) //<Sebastian Markbåge>//
- **[657428a](react/react@657428a9e )**: Add ReactNativeTypes for root options ([#28850](react/react#28850)) //<Ricky>//
- **[7909d8e](react/react@7909d8eab )**: [Flight] Encode ReadableStream and AsyncIterables ([#28847](react/react#28847)) //<Sebastian Markbåge>//
- **[13eb61d](react/react@13eb61d05 )**: Move enableUseDeferredValueInitialArg to canary ([#28818](react/react#28818)) //<Andrew Clark>//
- **[8afa144](react/react@8afa144bd )**: Enable flag disableClientCache ([#28846](react/react#28846)) //<Jan Kassens>//
- **[734956a](react/react@734956ace )**: Devtools: Add support for useFormStatus ([#28413](react/react#28413)) //<Sebastian Silbermann>//
- **[17e920c](react/react@17e920c00 )**: [Flight Reply] Encode Typed Arrays and Blobs ([#28819](react/react#28819)) //<Sebastian Markbåge>//
- **[0347fcd](react/react@0347fcd00 )**: Add on(Caught|Uncaught|Recoverable) opts to RN ([#28836](react/react#28836)) //<Ricky>//
- **[c113503](react/react@c113503ad )**: Flush direct streams in Bun ([#28837](react/react#28837)) //<Kenta Iwasaki>//
- **[9defcd5](react/react@9defcd56b )**: Remove redundant props assign ([#28829](react/react#28829)) //<Sebastian Silbermann>//
- **[ed40236](react/react@ed4023603 )**: Fix mistaken "react-server" condition ([#28835](react/react#28835)) //<Sebastian Markbåge>//
- **[c8a0350](react/react@c8a035036 )**: [Fizz] hoistables should never flush before the preamble ([#28802](react/react#28802)) //<Josh Story>//
- **[4f5c812](react/react@4f5c812a3 )**: DevTools: Rely on sourcemaps to compute hook name of built-in hooks in newer versions ([#28593](react/react#28593)) //<Sebastian Silbermann>//
- **[4354159](react/react@435415962 )**: Backwards compatibility for string refs on WWW ([#28826](react/react#28826)) //<Jack Pope>//
- **[608edcc](react/react@608edcc90 )**: [tests] add `assertConsole<method>Dev` helpers ([#28732](react/react#28732)) //<Ricky>//
- **[da69b6a](react/react@da69b6af9 )**: ReactDOM.requestFormReset ([#28809](react/react#28809)) //<Andrew Clark>//
- **[374b5d2](react/react@374b5d26c )**: Scaffolding for requestFormReset API ([#28808](react/react#28808)) //<Andrew Clark>//
- **[41950d1](react/react@41950d14a )**: Automatically reset forms after action finishes ([#28804](react/react#28804)) //<Andrew Clark>//
- **[dc6a7e0](react/react@dc6a7e01e )**: [Float] Don't preload images inside `<noscript>` ([#28815](react/react#28815)) //<Josh Story>//
- **[3f947b1](react/react@3f947b1b4 )**: [tests] Assert scheduler log empty in internalAct ([#28737](react/react#28737)) //<Ricky>//
- **[bf09089](react/react@bf09089f6 )**: Remove Scheduler.log from ReactSuspenseFuzz-test ([#28812](react/react#28812)) //<Ricky>//
- **[84cb3b4](react/react@84cb3b4cb )**: Hardcode disableIEWorkarounds for www ([#28811](react/react#28811)) //<Ricky>//
- **[2243b40](react/react@2243b40ab )**: [tests] assertLog before act in useEffectEvent ([#28763](react/react#28763)) //<Ricky>//
- **[dfc64c6](react/react@dfc64c6e3 )**: [tests] assertLog before act in ReactUse ([#28762](react/react#28762)) //<Ricky>//
- **[42eff4b](react/react@42eff4bc7 )**: [tests] Fix assertions not flushed before act ([#28745](react/react#28745)) //<Ricky>//
- **[ed3c65c](react/react@ed3c65caf )**: Warn if outdated JSX transform is detected ([#28781](react/react#28781)) //<Andrew Clark>//
- **[3f9e237](react/react@3f9e237a2 )**: Fix: Suspend while recovering from hydration error ([#28800](react/react#28800)) //<Andrew Clark>//
- **[7f5d25e](react/react@7f5d25e23 )**: Fix cloneElement using string ref w no owner ([#28797](react/react#28797)) //<Joseph Savona>//
- **[bf40b02](react/react@bf40b0244 )**: [Fizz] Stop publishing external-runtime to stable channel ([#28796](react/react#28796)) //<Josh Story>//
- **[7f93cb4](react/react@7f93cb41c )**: [DOM] Infer react-server entries bundles if not explicitly configured ([#28795](react/react#28795)) //<Josh Story>//
- **[f613165](react/react@f61316535 )**: Rename SECRET INTERNALS to `__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE` ([#28789](react/react#28789)) //<Sebastian Markbåge>//
- **[9644d20](react/react@9644d206e )**: Soften useFormState warning ([#28788](react/react#28788)) //<Ricky>//
- **[c771016](react/react@c771016e1 )**: Rename The Secret Export of Server Internals ([#28786](react/react#28786)) //<Sebastian Markbåge>//
- **[d50323e](react/react@d50323eb8 )**: Flatten ReactSharedInternals ([#28783](react/react#28783)) //<Sebastian Markbåge>//
- **[f62cf8c](react/react@f62cf8c62 )**: [Float] treat `props.async` in Float consistent with the rest of react-dom ([#26760](react/react#26760)) //<Josh Story>//
- **[dfd3d5a](react/react@dfd3d5af8 )**: Add support for transition{run,start,cancel} events ([#27345](react/react#27345)) //<Hugo Sales>//
- **[1f8327f](react/react@1f8327f83 )**: [Fiber] Use real event priority for hydration scheduling ([#28765](react/react#28765)) //<Josh Story>//
- **[97c90ed](react/react@97c90ed88 )**: [DOM] Shrink ReactDOMCurrentDispatcher method names ([#28770](react/react#28770)) //<Josh Story>//
- **[9007fdc](react/react@9007fdc8f )**: [DOM] Shrink ReactDOMSharedInternals source representation ([#28771](react/react#28771)) //<Josh Story>//
- **[14f50ad](react/react@14f50ad15 )**: [Flight] Allow lazily resolving outlined models ([#28780](react/react#28780)) //<Sebastian Markbåge>//
- **[4c12339](react/react@4c12339ce )**: [DOM] move `flushSync` out of the reconciler ([#28500](react/react#28500)) //<Josh Story>//
- **[8e1462e](react/react@8e1462e8c )**: [Fiber] Move updatePriority tracking to renderers ([#28751](react/react#28751)) //<Josh Story>//
- **[0b3b8a6](react/react@0b3b8a6a3 )**: jsx: Remove unnecessary hasOwnProperty check ([#28775](react/react#28775)) //<Andrew Clark>//
- **[2acfb7b](react/react@2acfb7b60 )**: [Flight] Support FormData from Server to Client ([#28754](react/react#28754)) //<Sebastian Markbåge>//
- **[d1547de](react/react@d1547defe )**: Fast JSX: Don't clone props object ([#28768](react/react#28768)) //<Andrew Clark>//
- **[bfd8da8](react/react@bfd8da807 )**: Make class prop resolution faster ([#28766](react/react#28766)) //<Andrew Clark>//
- **[cbb6f2b](react/react@cbb6f2b54 )**: [Flight] Support Blobs from Server to Client ([#28755](react/react#28755)) //<Sebastian Markbåge>//
- **[f33a6b6](react/react@f33a6b69c )**: Track Owner for Server Components in DEV ([#28753](react/react#28753)) //<Sebastian Markbåge>//
- **[e3ebcd5](react/react@e3ebcd54b )**: Move string ref coercion to JSX runtime ([#28473](react/react#28473)) //<Andrew Clark>//
- **[fd0da3e](react/react@fd0da3eef )**: Remove _owner field from JSX elements in prod if string refs are disabled ([#28739](react/react#28739)) //<Sebastian Markbåge>//
Changelog:
[General][Changed] - React Native sync for revisions 48b4ecc...b5e5ce8
jest_e2e[run_all_tests]
bypass-github-export-checks
Reviewed By: kassens
Differential Revision: D56251607
fbshipit-source-id: e16db2fa101fc7ed1e009158c76388206beabd5f
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA SignedReact Core TeamOpened by a member of the React Core Team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@acdlite@react-sizebot@sebmarkbage@gnoff@facebook-github-bot
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Automatically reset forms after action finishes - #28804

Merged
acdlite merged 1 commit into
react:mainfrom
acdlite:automatically-reset-forms
Apr 10, 2024
Merged

Automatically reset forms after action finishes#28804
acdlite merged 1 commit into
react:mainfrom
acdlite:automatically-reset-forms

Conversation

@acdlite

Copy link
Copy Markdown
Collaborator

This updates the behavior of form actions to automatically reset the form's uncontrolled inputs after the action finishes.

This is a frequent feature request for people using actions and it aligns the behavior of client-side form submissions more closely with MPA form submissions.

It has no impact on controlled form inputs. It's the same as if you called form.reset() manually, except React handles the timing of when the reset happens, which is tricky/impossible to get exactly right in userspace.

The reset shouldn't happen until the UI has updated with the result of the action. So, resetting inside the action is too early.

Resetting in useEffect is better, but it's later than ideal because any effects that run before it will observe the state of the form before it's been reset.

It needs to happen in the mutation phase of the transition. More specifically, after all the DOM mutations caused by the transition have been applied. That way the defaultValue of the inputs are updated before the values are reset. The idea is that the defaultValue represents the current, canonical value sent by the server.

Note: this change has no effect on form submissions that aren't triggered by an action.

@facebook-github-botfacebook-github-bot added CLA Signed React Core Team Opened by a member of the React Core Team labels Apr 10, 2024
@react-sizebot

react-sizebot commented Apr 10, 2024

Copy link
Copy Markdown

Comparing: ed3c65c...562f9c9

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name+/-BaseCurrent+/- gzipBase gzipCurrent gzip
oss-stable/react-dom/cjs/react-dom.production.min.js+0.27%168.12 kB168.57 kB+0.24%52.72 kB52.85 kB
oss-experimental/react-dom/cjs/react-dom.production.min.js+0.26%169.92 kB170.37 kB+0.20%53.26 kB53.37 kB
facebook-www/ReactDOM-prod.classic.js+0.22%589.57 kB590.89 kB+0.22%103.80 kB104.03 kB
facebook-www/ReactDOM-prod.modern.js+0.23%565.41 kB566.73 kB+0.23%99.93 kB100.16 kB
test_utils/ReactAllWarnings.jsDeleted64.24 kB0.00 kBDeleted16.03 kB0.00 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name+/-BaseCurrent+/- gzipBase gzipCurrent gzip
oss-stable-semver/react-reconciler/cjs/react-reconciler.production.js+0.49%665.84 kB669.08 kB+0.51%146.23 kB146.97 kB
oss-stable/react-reconciler/cjs/react-reconciler.production.js+0.49%665.86 kB669.11 kB+0.51%146.26 kB147.01 kB
oss-experimental/react-reconciler/cjs/react-reconciler.production.js+0.48%672.88 kB676.12 kB+0.53%147.79 kB148.57 kB
oss-stable-semver/react-reconciler/cjs/react-reconciler.development.js+0.48%908.86 kB913.24 kB+0.53%195.30 kB196.34 kB
oss-stable/react-reconciler/cjs/react-reconciler.development.js+0.48%908.89 kB913.27 kB+0.53%195.33 kB196.37 kB
oss-experimental/react-reconciler/cjs/react-reconciler.development.js+0.48%918.20 kB922.58 kB+0.53%197.14 kB198.19 kB
oss-stable-semver/react-reconciler/cjs/react-reconciler.profiling.js+0.46%705.86 kB709.10 kB+0.50%153.52 kB154.29 kB
oss-stable/react-reconciler/cjs/react-reconciler.profiling.js+0.46%705.89 kB709.13 kB+0.50%153.55 kB154.31 kB
oss-experimental/react-reconciler/cjs/react-reconciler.profiling.js+0.46%712.90 kB716.14 kB+0.49%155.11 kB155.88 kB
oss-stable-semver/react-reconciler/cjs/react-reconciler.production.min.js+0.43%108.56 kB109.03 kB+0.39%33.85 kB33.98 kB
oss-stable/react-reconciler/cjs/react-reconciler.production.min.js+0.43%108.59 kB109.06 kB+0.39%33.87 kB34.00 kB
oss-experimental/react-reconciler/cjs/react-reconciler.production.min.js+0.42%110.35 kB110.82 kB+0.37%34.47 kB34.60 kB
oss-stable-semver/react-reconciler/cjs/react-reconciler.profiling.min.js+0.40%117.42 kB117.89 kB+0.32%36.09 kB36.21 kB
oss-stable/react-reconciler/cjs/react-reconciler.profiling.min.js+0.40%117.45 kB117.92 kB+0.33%36.11 kB36.23 kB
oss-experimental/react-reconciler/cjs/react-reconciler.profiling.min.js+0.39%119.21 kB119.67 kB+0.41%36.65 kB36.80 kB
oss-stable-semver/react-dom/cjs/react-dom.production.js+0.35%919.85 kB923.06 kB+0.37%206.89 kB207.65 kB
oss-stable/react-dom/cjs/react-dom.production.js+0.35%919.87 kB923.08 kB+0.37%206.92 kB207.68 kB
oss-experimental/react-dom/cjs/react-dom.production.js+0.35%926.94 kB930.15 kB+0.37%208.43 kB209.20 kB
oss-experimental/react-dom/cjs/react-dom-unstable_testing.production.js+0.34%945.18 kB948.39 kB+0.36%212.95 kB213.71 kB
oss-stable-semver/react-dom/cjs/react-dom.development.js+0.34%1,293.34 kB1,297.68 kB+0.37%286.49 kB287.55 kB
oss-stable/react-dom/cjs/react-dom.development.js+0.34%1,293.36 kB1,297.71 kB+0.37%286.52 kB287.58 kB
oss-stable-semver/react-dom/umd/react-dom.development.js+0.34%1,356.09 kB1,360.63 kB+0.38%289.40 kB290.49 kB
oss-stable/react-dom/umd/react-dom.development.js+0.34%1,356.12 kB1,360.66 kB+0.38%289.43 kB290.52 kB
oss-stable-semver/react-dom/cjs/react-dom.profiling.js+0.33%960.46 kB963.67 kB+0.35%214.16 kB214.92 kB
oss-stable/react-dom/cjs/react-dom.profiling.js+0.33%960.48 kB963.69 kB+0.35%214.19 kB214.95 kB
oss-experimental/react-dom/cjs/react-dom.development.js+0.33%1,302.73 kB1,307.08 kB+0.37%288.32 kB289.39 kB
oss-experimental/react-dom/umd/react-dom.development.js+0.33%1,365.97 kB1,370.51 kB+0.36%291.21 kB292.26 kB
oss-experimental/react-dom/cjs/react-dom.profiling.js+0.33%967.55 kB970.76 kB+0.35%215.71 kB216.46 kB
oss-experimental/react-dom/cjs/react-dom-unstable_testing.development.js+0.33%1,321.15 kB1,325.50 kB+0.37%292.77 kB293.84 kB
facebook-www/ReactDOM-dev.modern.js+0.30%1,621.20 kB1,626.01 kB+0.34%322.53 kB323.63 kB
facebook-www/ReactDOMTesting-dev.modern.js+0.29%1,644.60 kB1,649.41 kB+0.34%327.14 kB328.26 kB
facebook-www/ReactDOM-dev.classic.js+0.29%1,673.24 kB1,678.05 kB+0.34%331.38 kB332.50 kB
facebook-www/ReactDOMTesting-dev.classic.js+0.28%1,697.92 kB1,702.73 kB+0.33%336.19 kB337.31 kB
oss-stable-semver/react-dom/umd/react-dom.production.min.js+0.27%167.79 kB168.24 kB+0.28%53.04 kB53.19 kB
oss-stable/react-dom/umd/react-dom.production.min.js+0.27%167.87 kB168.32 kB+0.28%53.07 kB53.22 kB
oss-stable-semver/react-dom/cjs/react-dom.production.min.js+0.27%168.04 kB168.49 kB+0.24%52.69 kB52.82 kB
oss-stable/react-dom/cjs/react-dom.production.min.js+0.27%168.12 kB168.57 kB+0.24%52.72 kB52.85 kB
oss-experimental/react-dom/umd/react-dom.production.min.js+0.27%169.67 kB170.13 kB+0.25%53.70 kB53.83 kB
oss-experimental/react-dom/cjs/react-dom.production.min.js+0.26%169.92 kB170.37 kB+0.20%53.26 kB53.37 kB
oss-stable-semver/react-dom/umd/react-dom.profiling.min.js+0.25%176.63 kB177.08 kB+0.21%55.45 kB55.56 kB
oss-stable/react-dom/umd/react-dom.profiling.min.js+0.25%176.71 kB177.16 kB+0.21%55.47 kB55.59 kB
oss-experimental/react-dom/cjs/react-dom-unstable_testing.production.min.js+0.25%176.86 kB177.31 kB+0.20%55.85 kB55.97 kB
oss-stable-semver/react-dom/cjs/react-dom.profiling.min.js+0.25%177.32 kB177.77 kB+0.22%55.14 kB55.26 kB
oss-stable/react-dom/cjs/react-dom.profiling.min.js+0.25%177.40 kB177.85 kB+0.22%55.16 kB55.28 kB
oss-experimental/react-dom/umd/react-dom.profiling.min.js+0.25%178.51 kB178.96 kB+0.25%56.01 kB56.15 kB
oss-experimental/react-dom/cjs/react-dom.profiling.min.js+0.25%179.21 kB179.66 kB+0.25%55.71 kB55.85 kB
facebook-www/ReactDOM-prod.modern.js+0.23%565.41 kB566.73 kB+0.23%99.93 kB100.16 kB
facebook-www/ReactDOMTesting-prod.modern.js+0.23%581.36 kB582.67 kB+0.22%103.88 kB104.11 kB
facebook-www/ReactDOM-prod.classic.js+0.22%589.57 kB590.89 kB+0.22%103.80 kB104.03 kB
facebook-www/ReactDOM-profiling.modern.js+0.22%594.31 kB595.63 kB+0.22%104.07 kB104.29 kB
facebook-www/ReactDOMTesting-prod.classic.js+0.22%604.22 kB605.54 kB+0.21%107.51 kB107.74 kB
facebook-www/ReactDOM-profiling.classic.js+0.21%619.11 kB620.43 kB+0.22%108.10 kB108.33 kB
test_utils/ReactAllWarnings.jsDeleted64.24 kB0.00 kBDeleted16.03 kB0.00 kB

Generated by 🚫 dangerJS against 562f9c9

@acdlite
acdliteforce-pushed the automatically-reset-forms branch 2 times, most recently from 5e8fad4 to 41e6173CompareApril 10, 2024 00:38
@acdlite
acdlite marked this pull request as ready for review April 10, 2024 00:41

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should start a campaign for javascript64

@acdliteacdlite mentioned this pull request Apr 10, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right
in userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
@acdlite
acdliteforce-pushed the automatically-reset-forms branch from 41e6173 to 562f9c9CompareApril 10, 2024 04:04
const newResetState = {};
const resetStateHook: Hook = (formFiber.memoizedState.next: any);
const resetStateQueue = resetStateHook.queue;
dispatchSetState(formFiber, resetStateQueue, newResetState);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this actually have to be on the Fiber?

Can't it just be scheduled on the Root with a list of forms to reset when the root commits?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That way you don't need all the special commit phase stuff.

@acdliteacdliteApr 10, 2024

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm I'll need to think more about that, the scenario I had in mind was if the form is inside a Suspense boundary, the root could commit before the input's defaultValue had been updated. Usually this shouldn't happen because during a Transition we won't hide already visible forms, but during a popstate transition we might.

The <input form="myform"> case is interesting there, too.

@acdlite
acdlite merged commit 41950d1 into react:mainApr 10, 2024
acdlite added a commit that referenced this pull request Apr 10, 2024
Based on:
- #28804 ---
This sets adds a new ReactDOM export called requestFormReset, including
setting up the export and creating a method on the internal ReactDOM
dispatcher. It does not yet add any implementation.
Doing this in its own commit for review purposes.
The API itself will be explained in the next PR.
acdlite added a commit that referenced this pull request Apr 10, 2024
Based on:
- #28808
- #28804 ---
This adds a React DOM method called requestFormReset that schedules a
form reset to occur when the current transition completes.
Internally, it's the same method that's called automatically whenever a
form action is submitted. It only affects uncontrolled form inputs. See
#28804 for details.
The reason for the public API is so UI libraries can implement their own
action-based APIs and maintain the form-resetting behavior, something
like this:
```js
function onSubmit(event) {
// Disable default form submission behavior
event.preventDefault();
const form = event.target;
startTransition(async () => {
// Request the form to reset once the action
// has completed
requestFormReset(form);
// Call the user-provided action prop
await action(new FormData(form));
})
}
```
github-actionsBot pushed a commit that referenced this pull request Apr 10, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right in
userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
DiffTrain build for [41950d1](41950d1)
github-actionsBot pushed a commit that referenced this pull request Apr 10, 2024
Based on:
- #28804
---
This sets adds a new ReactDOM export called requestFormReset, including
setting up the export and creating a method on the internal ReactDOM
dispatcher. It does not yet add any implementation.
Doing this in its own commit for review purposes.
The API itself will be explained in the next PR.
DiffTrain build for [374b5d2](374b5d2)
github-actionsBot pushed a commit that referenced this pull request Apr 10, 2024
Based on:
- #28808
- #28804
---
This adds a React DOM method called requestFormReset that schedules a
form reset to occur when the current transition completes.
Internally, it's the same method that's called automatically whenever a
form action is submitted. It only affects uncontrolled form inputs. See
#28804 for details.
The reason for the public API is so UI libraries can implement their own
action-based APIs and maintain the form-resetting behavior, something
like this:
```js
function onSubmit(event) {
// Disable default form submission behavior
event.preventDefault();
const form = event.target;
startTransition(async () => {
// Request the form to reset once the action
// has completed
requestFormReset(form);
// Call the user-provided action prop
await action(new FormData(form));
})
}
```
DiffTrain build for [da69b6a](da69b6a)
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right in
userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
Based on:
- #28804 ---
This sets adds a new ReactDOM export called requestFormReset, including
setting up the export and creating a method on the internal ReactDOM
dispatcher. It does not yet add any implementation.
Doing this in its own commit for review purposes.
The API itself will be explained in the next PR.
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
Based on:
- #28808
- #28804 ---
This adds a React DOM method called requestFormReset that schedules a
form reset to occur when the current transition completes.
Internally, it's the same method that's called automatically whenever a
form action is submitted. It only affects uncontrolled form inputs. See
#28804 for details.
The reason for the public API is so UI libraries can implement their own
action-based APIs and maintain the form-resetting behavior, something
like this:
```js
function onSubmit(event) {
// Disable default form submission behavior
event.preventDefault();
const form = event.target;
startTransition(async () => {
// Request the form to reset once the action
// has completed
requestFormReset(form);
// Call the user-provided action prop
await action(new FormData(form));
})
}
```
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right in
userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
Based on:
- #28804 ---
This sets adds a new ReactDOM export called requestFormReset, including
setting up the export and creating a method on the internal ReactDOM
dispatcher. It does not yet add any implementation.
Doing this in its own commit for review purposes.
The API itself will be explained in the next PR.
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
Based on:
- #28808
- #28804 ---
This adds a React DOM method called requestFormReset that schedules a
form reset to occur when the current transition completes.
Internally, it's the same method that's called automatically whenever a
form action is submitted. It only affects uncontrolled form inputs. See
#28804 for details.
The reason for the public API is so UI libraries can implement their own
action-based APIs and maintain the form-resetting behavior, something
like this:
```js
function onSubmit(event) {
// Disable default form submission behavior
event.preventDefault();
const form = event.target;
startTransition(async () => {
// Request the form to reset once the action
// has completed
requestFormReset(form);
// Call the user-provided action prop
await action(new FormData(form));
})
}
```
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right in
userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
Based on:
- react#28804 ---
This sets adds a new ReactDOM export called requestFormReset, including
setting up the export and creating a method on the internal ReactDOM
dispatcher. It does not yet add any implementation.
Doing this in its own commit for review purposes.
The API itself will be explained in the next PR.
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
Based on:
- react#28808
- react#28804 ---
This adds a React DOM method called requestFormReset that schedules a
form reset to occur when the current transition completes.
Internally, it's the same method that's called automatically whenever a
form action is submitted. It only affects uncontrolled form inputs. See
react#28804 for details.
The reason for the public API is so UI libraries can implement their own
action-based APIs and maintain the form-resetting behavior, something
like this:
```js
function onSubmit(event) {
// Disable default form submission behavior
event.preventDefault();
const form = event.target;
startTransition(async () => {
// Request the form to reset once the action
// has completed
requestFormReset(form);
// Call the user-provided action prop
await action(new FormData(form));
})
}
```
bigfootjon pushed a commit that referenced this pull request Apr 18, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right in
userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
DiffTrain build for commit 41950d1.
facebook-github-bot pushed a commit to react/react-native that referenced this pull request Apr 19, 2024
Summary:
This sync includes the changes from:
- D56103750
- [TODO] A shim for SECRET_INTERNALS
This sync includes the following changes:
- **[b5e5ce8](react/react@b5e5ce8e0 )**: Update ReactNativeTypes for root options (part 2) ([#28857](react/react#28857)) //<Ricky>//
- **[da6ba53](react/react@da6ba53b1 )**: [UMD] Remove umd builds ([#28735](react/react#28735)) //<Josh Story>//
- **[0c245df](react/react@0c245df1d )**: Complete the typo fix ([#28856](react/react#28856)) //<Sebastian Silbermann>//
- **[f82051d](react/react@f82051d7a )**: console test utils fix: match entire string, not just first letter ([#28855](react/react#28855)) //<Andrew Clark>//
- **[4ca20fd](react/react@4ca20fd36 )**: Test top level fragment inside lazy semantics ([#28852](react/react#28852)) //<Sebastian Markbåge>//
- **[c0cf7c6](react/react@c0cf7c696 )**: Promote ASYNC_ITERATOR symbol to React Symbols ([#28851](react/react#28851)) //<Sebastian Markbåge>//
- **[657428a](react/react@657428a9e )**: Add ReactNativeTypes for root options ([#28850](react/react#28850)) //<Ricky>//
- **[7909d8e](react/react@7909d8eab )**: [Flight] Encode ReadableStream and AsyncIterables ([#28847](react/react#28847)) //<Sebastian Markbåge>//
- **[13eb61d](react/react@13eb61d05 )**: Move enableUseDeferredValueInitialArg to canary ([#28818](react/react#28818)) //<Andrew Clark>//
- **[8afa144](react/react@8afa144bd )**: Enable flag disableClientCache ([#28846](react/react#28846)) //<Jan Kassens>//
- **[734956a](react/react@734956ace )**: Devtools: Add support for useFormStatus ([#28413](react/react#28413)) //<Sebastian Silbermann>//
- **[17e920c](react/react@17e920c00 )**: [Flight Reply] Encode Typed Arrays and Blobs ([#28819](react/react#28819)) //<Sebastian Markbåge>//
- **[0347fcd](react/react@0347fcd00 )**: Add on(Caught|Uncaught|Recoverable) opts to RN ([#28836](react/react#28836)) //<Ricky>//
- **[c113503](react/react@c113503ad )**: Flush direct streams in Bun ([#28837](react/react#28837)) //<Kenta Iwasaki>//
- **[9defcd5](react/react@9defcd56b )**: Remove redundant props assign ([#28829](react/react#28829)) //<Sebastian Silbermann>//
- **[ed40236](react/react@ed4023603 )**: Fix mistaken "react-server" condition ([#28835](react/react#28835)) //<Sebastian Markbåge>//
- **[c8a0350](react/react@c8a035036 )**: [Fizz] hoistables should never flush before the preamble ([#28802](react/react#28802)) //<Josh Story>//
- **[4f5c812](react/react@4f5c812a3 )**: DevTools: Rely on sourcemaps to compute hook name of built-in hooks in newer versions ([#28593](react/react#28593)) //<Sebastian Silbermann>//
- **[4354159](react/react@435415962 )**: Backwards compatibility for string refs on WWW ([#28826](react/react#28826)) //<Jack Pope>//
- **[608edcc](react/react@608edcc90 )**: [tests] add `assertConsole<method>Dev` helpers ([#28732](react/react#28732)) //<Ricky>//
- **[da69b6a](react/react@da69b6af9 )**: ReactDOM.requestFormReset ([#28809](react/react#28809)) //<Andrew Clark>//
- **[374b5d2](react/react@374b5d26c )**: Scaffolding for requestFormReset API ([#28808](react/react#28808)) //<Andrew Clark>//
- **[41950d1](react/react@41950d14a )**: Automatically reset forms after action finishes ([#28804](react/react#28804)) //<Andrew Clark>//
- **[dc6a7e0](react/react@dc6a7e01e )**: [Float] Don't preload images inside `<noscript>` ([#28815](react/react#28815)) //<Josh Story>//
- **[3f947b1](react/react@3f947b1b4 )**: [tests] Assert scheduler log empty in internalAct ([#28737](react/react#28737)) //<Ricky>//
- **[bf09089](react/react@bf09089f6 )**: Remove Scheduler.log from ReactSuspenseFuzz-test ([#28812](react/react#28812)) //<Ricky>//
- **[84cb3b4](react/react@84cb3b4cb )**: Hardcode disableIEWorkarounds for www ([#28811](react/react#28811)) //<Ricky>//
- **[2243b40](react/react@2243b40ab )**: [tests] assertLog before act in useEffectEvent ([#28763](react/react#28763)) //<Ricky>//
- **[dfc64c6](react/react@dfc64c6e3 )**: [tests] assertLog before act in ReactUse ([#28762](react/react#28762)) //<Ricky>//
- **[42eff4b](react/react@42eff4bc7 )**: [tests] Fix assertions not flushed before act ([#28745](react/react#28745)) //<Ricky>//
- **[ed3c65c](react/react@ed3c65caf )**: Warn if outdated JSX transform is detected ([#28781](react/react#28781)) //<Andrew Clark>//
- **[3f9e237](react/react@3f9e237a2 )**: Fix: Suspend while recovering from hydration error ([#28800](react/react#28800)) //<Andrew Clark>//
- **[7f5d25e](react/react@7f5d25e23 )**: Fix cloneElement using string ref w no owner ([#28797](react/react#28797)) //<Joseph Savona>//
- **[bf40b02](react/react@bf40b0244 )**: [Fizz] Stop publishing external-runtime to stable channel ([#28796](react/react#28796)) //<Josh Story>//
- **[7f93cb4](react/react@7f93cb41c )**: [DOM] Infer react-server entries bundles if not explicitly configured ([#28795](react/react#28795)) //<Josh Story>//
- **[f613165](react/react@f61316535 )**: Rename SECRET INTERNALS to `__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE` ([#28789](react/react#28789)) //<Sebastian Markbåge>//
- **[9644d20](react/react@9644d206e )**: Soften useFormState warning ([#28788](react/react#28788)) //<Ricky>//
- **[c771016](react/react@c771016e1 )**: Rename The Secret Export of Server Internals ([#28786](react/react#28786)) //<Sebastian Markbåge>//
- **[d50323e](react/react@d50323eb8 )**: Flatten ReactSharedInternals ([#28783](react/react#28783)) //<Sebastian Markbåge>//
- **[f62cf8c](react/react@f62cf8c62 )**: [Float] treat `props.async` in Float consistent with the rest of react-dom ([#26760](react/react#26760)) //<Josh Story>//
- **[dfd3d5a](react/react@dfd3d5af8 )**: Add support for transition{run,start,cancel} events ([#27345](react/react#27345)) //<Hugo Sales>//
- **[1f8327f](react/react@1f8327f83 )**: [Fiber] Use real event priority for hydration scheduling ([#28765](react/react#28765)) //<Josh Story>//
- **[97c90ed](react/react@97c90ed88 )**: [DOM] Shrink ReactDOMCurrentDispatcher method names ([#28770](react/react#28770)) //<Josh Story>//
- **[9007fdc](react/react@9007fdc8f )**: [DOM] Shrink ReactDOMSharedInternals source representation ([#28771](react/react#28771)) //<Josh Story>//
- **[14f50ad](react/react@14f50ad15 )**: [Flight] Allow lazily resolving outlined models ([#28780](react/react#28780)) //<Sebastian Markbåge>//
- **[4c12339](react/react@4c12339ce )**: [DOM] move `flushSync` out of the reconciler ([#28500](react/react#28500)) //<Josh Story>//
- **[8e1462e](react/react@8e1462e8c )**: [Fiber] Move updatePriority tracking to renderers ([#28751](react/react#28751)) //<Josh Story>//
- **[0b3b8a6](react/react@0b3b8a6a3 )**: jsx: Remove unnecessary hasOwnProperty check ([#28775](react/react#28775)) //<Andrew Clark>//
- **[2acfb7b](react/react@2acfb7b60 )**: [Flight] Support FormData from Server to Client ([#28754](react/react#28754)) //<Sebastian Markbåge>//
- **[d1547de](react/react@d1547defe )**: Fast JSX: Don't clone props object ([#28768](react/react#28768)) //<Andrew Clark>//
- **[bfd8da8](react/react@bfd8da807 )**: Make class prop resolution faster ([#28766](react/react#28766)) //<Andrew Clark>//
- **[cbb6f2b](react/react@cbb6f2b54 )**: [Flight] Support Blobs from Server to Client ([#28755](react/react#28755)) //<Sebastian Markbåge>//
- **[f33a6b6](react/react@f33a6b69c )**: Track Owner for Server Components in DEV ([#28753](react/react#28753)) //<Sebastian Markbåge>//
- **[e3ebcd5](react/react@e3ebcd54b )**: Move string ref coercion to JSX runtime ([#28473](react/react#28473)) //<Andrew Clark>//
- **[fd0da3e](react/react@fd0da3eef )**: Remove _owner field from JSX elements in prod if string refs are disabled ([#28739](react/react#28739)) //<Sebastian Markbåge>//
Changelog:
[General][Changed] - React Native sync for revisions 48b4ecc...b5e5ce8
jest_e2e[run_all_tests]
bypass-github-export-checks
Reviewed By: kassens
Differential Revision: D56251607
fbshipit-source-id: e16db2fa101fc7ed1e009158c76388206beabd5f
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA SignedReact Core TeamOpened by a member of the React Core Team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@acdlite@react-sizebot@sebmarkbage@gnoff@facebook-github-bot
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Automatically reset forms after action finishes - #28804

Merged
acdlite merged 1 commit into
react:mainfrom
acdlite:automatically-reset-forms
Apr 10, 2024
Merged

Automatically reset forms after action finishes#28804
acdlite merged 1 commit into
react:mainfrom
acdlite:automatically-reset-forms

Conversation

@acdlite

Copy link
Copy Markdown
Collaborator

This updates the behavior of form actions to automatically reset the form's uncontrolled inputs after the action finishes.

This is a frequent feature request for people using actions and it aligns the behavior of client-side form submissions more closely with MPA form submissions.

It has no impact on controlled form inputs. It's the same as if you called form.reset() manually, except React handles the timing of when the reset happens, which is tricky/impossible to get exactly right in userspace.

The reset shouldn't happen until the UI has updated with the result of the action. So, resetting inside the action is too early.

Resetting in useEffect is better, but it's later than ideal because any effects that run before it will observe the state of the form before it's been reset.

It needs to happen in the mutation phase of the transition. More specifically, after all the DOM mutations caused by the transition have been applied. That way the defaultValue of the inputs are updated before the values are reset. The idea is that the defaultValue represents the current, canonical value sent by the server.

Note: this change has no effect on form submissions that aren't triggered by an action.

@facebook-github-botfacebook-github-bot added CLA Signed React Core Team Opened by a member of the React Core Team labels Apr 10, 2024
@react-sizebot

react-sizebot commented Apr 10, 2024

Copy link
Copy Markdown

Comparing: ed3c65c...562f9c9

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name+/-BaseCurrent+/- gzipBase gzipCurrent gzip
oss-stable/react-dom/cjs/react-dom.production.min.js+0.27%168.12 kB168.57 kB+0.24%52.72 kB52.85 kB
oss-experimental/react-dom/cjs/react-dom.production.min.js+0.26%169.92 kB170.37 kB+0.20%53.26 kB53.37 kB
facebook-www/ReactDOM-prod.classic.js+0.22%589.57 kB590.89 kB+0.22%103.80 kB104.03 kB
facebook-www/ReactDOM-prod.modern.js+0.23%565.41 kB566.73 kB+0.23%99.93 kB100.16 kB
test_utils/ReactAllWarnings.jsDeleted64.24 kB0.00 kBDeleted16.03 kB0.00 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name+/-BaseCurrent+/- gzipBase gzipCurrent gzip
oss-stable-semver/react-reconciler/cjs/react-reconciler.production.js+0.49%665.84 kB669.08 kB+0.51%146.23 kB146.97 kB
oss-stable/react-reconciler/cjs/react-reconciler.production.js+0.49%665.86 kB669.11 kB+0.51%146.26 kB147.01 kB
oss-experimental/react-reconciler/cjs/react-reconciler.production.js+0.48%672.88 kB676.12 kB+0.53%147.79 kB148.57 kB
oss-stable-semver/react-reconciler/cjs/react-reconciler.development.js+0.48%908.86 kB913.24 kB+0.53%195.30 kB196.34 kB
oss-stable/react-reconciler/cjs/react-reconciler.development.js+0.48%908.89 kB913.27 kB+0.53%195.33 kB196.37 kB
oss-experimental/react-reconciler/cjs/react-reconciler.development.js+0.48%918.20 kB922.58 kB+0.53%197.14 kB198.19 kB
oss-stable-semver/react-reconciler/cjs/react-reconciler.profiling.js+0.46%705.86 kB709.10 kB+0.50%153.52 kB154.29 kB
oss-stable/react-reconciler/cjs/react-reconciler.profiling.js+0.46%705.89 kB709.13 kB+0.50%153.55 kB154.31 kB
oss-experimental/react-reconciler/cjs/react-reconciler.profiling.js+0.46%712.90 kB716.14 kB+0.49%155.11 kB155.88 kB
oss-stable-semver/react-reconciler/cjs/react-reconciler.production.min.js+0.43%108.56 kB109.03 kB+0.39%33.85 kB33.98 kB
oss-stable/react-reconciler/cjs/react-reconciler.production.min.js+0.43%108.59 kB109.06 kB+0.39%33.87 kB34.00 kB
oss-experimental/react-reconciler/cjs/react-reconciler.production.min.js+0.42%110.35 kB110.82 kB+0.37%34.47 kB34.60 kB
oss-stable-semver/react-reconciler/cjs/react-reconciler.profiling.min.js+0.40%117.42 kB117.89 kB+0.32%36.09 kB36.21 kB
oss-stable/react-reconciler/cjs/react-reconciler.profiling.min.js+0.40%117.45 kB117.92 kB+0.33%36.11 kB36.23 kB
oss-experimental/react-reconciler/cjs/react-reconciler.profiling.min.js+0.39%119.21 kB119.67 kB+0.41%36.65 kB36.80 kB
oss-stable-semver/react-dom/cjs/react-dom.production.js+0.35%919.85 kB923.06 kB+0.37%206.89 kB207.65 kB
oss-stable/react-dom/cjs/react-dom.production.js+0.35%919.87 kB923.08 kB+0.37%206.92 kB207.68 kB
oss-experimental/react-dom/cjs/react-dom.production.js+0.35%926.94 kB930.15 kB+0.37%208.43 kB209.20 kB
oss-experimental/react-dom/cjs/react-dom-unstable_testing.production.js+0.34%945.18 kB948.39 kB+0.36%212.95 kB213.71 kB
oss-stable-semver/react-dom/cjs/react-dom.development.js+0.34%1,293.34 kB1,297.68 kB+0.37%286.49 kB287.55 kB
oss-stable/react-dom/cjs/react-dom.development.js+0.34%1,293.36 kB1,297.71 kB+0.37%286.52 kB287.58 kB
oss-stable-semver/react-dom/umd/react-dom.development.js+0.34%1,356.09 kB1,360.63 kB+0.38%289.40 kB290.49 kB
oss-stable/react-dom/umd/react-dom.development.js+0.34%1,356.12 kB1,360.66 kB+0.38%289.43 kB290.52 kB
oss-stable-semver/react-dom/cjs/react-dom.profiling.js+0.33%960.46 kB963.67 kB+0.35%214.16 kB214.92 kB
oss-stable/react-dom/cjs/react-dom.profiling.js+0.33%960.48 kB963.69 kB+0.35%214.19 kB214.95 kB
oss-experimental/react-dom/cjs/react-dom.development.js+0.33%1,302.73 kB1,307.08 kB+0.37%288.32 kB289.39 kB
oss-experimental/react-dom/umd/react-dom.development.js+0.33%1,365.97 kB1,370.51 kB+0.36%291.21 kB292.26 kB
oss-experimental/react-dom/cjs/react-dom.profiling.js+0.33%967.55 kB970.76 kB+0.35%215.71 kB216.46 kB
oss-experimental/react-dom/cjs/react-dom-unstable_testing.development.js+0.33%1,321.15 kB1,325.50 kB+0.37%292.77 kB293.84 kB
facebook-www/ReactDOM-dev.modern.js+0.30%1,621.20 kB1,626.01 kB+0.34%322.53 kB323.63 kB
facebook-www/ReactDOMTesting-dev.modern.js+0.29%1,644.60 kB1,649.41 kB+0.34%327.14 kB328.26 kB
facebook-www/ReactDOM-dev.classic.js+0.29%1,673.24 kB1,678.05 kB+0.34%331.38 kB332.50 kB
facebook-www/ReactDOMTesting-dev.classic.js+0.28%1,697.92 kB1,702.73 kB+0.33%336.19 kB337.31 kB
oss-stable-semver/react-dom/umd/react-dom.production.min.js+0.27%167.79 kB168.24 kB+0.28%53.04 kB53.19 kB
oss-stable/react-dom/umd/react-dom.production.min.js+0.27%167.87 kB168.32 kB+0.28%53.07 kB53.22 kB
oss-stable-semver/react-dom/cjs/react-dom.production.min.js+0.27%168.04 kB168.49 kB+0.24%52.69 kB52.82 kB
oss-stable/react-dom/cjs/react-dom.production.min.js+0.27%168.12 kB168.57 kB+0.24%52.72 kB52.85 kB
oss-experimental/react-dom/umd/react-dom.production.min.js+0.27%169.67 kB170.13 kB+0.25%53.70 kB53.83 kB
oss-experimental/react-dom/cjs/react-dom.production.min.js+0.26%169.92 kB170.37 kB+0.20%53.26 kB53.37 kB
oss-stable-semver/react-dom/umd/react-dom.profiling.min.js+0.25%176.63 kB177.08 kB+0.21%55.45 kB55.56 kB
oss-stable/react-dom/umd/react-dom.profiling.min.js+0.25%176.71 kB177.16 kB+0.21%55.47 kB55.59 kB
oss-experimental/react-dom/cjs/react-dom-unstable_testing.production.min.js+0.25%176.86 kB177.31 kB+0.20%55.85 kB55.97 kB
oss-stable-semver/react-dom/cjs/react-dom.profiling.min.js+0.25%177.32 kB177.77 kB+0.22%55.14 kB55.26 kB
oss-stable/react-dom/cjs/react-dom.profiling.min.js+0.25%177.40 kB177.85 kB+0.22%55.16 kB55.28 kB
oss-experimental/react-dom/umd/react-dom.profiling.min.js+0.25%178.51 kB178.96 kB+0.25%56.01 kB56.15 kB
oss-experimental/react-dom/cjs/react-dom.profiling.min.js+0.25%179.21 kB179.66 kB+0.25%55.71 kB55.85 kB
facebook-www/ReactDOM-prod.modern.js+0.23%565.41 kB566.73 kB+0.23%99.93 kB100.16 kB
facebook-www/ReactDOMTesting-prod.modern.js+0.23%581.36 kB582.67 kB+0.22%103.88 kB104.11 kB
facebook-www/ReactDOM-prod.classic.js+0.22%589.57 kB590.89 kB+0.22%103.80 kB104.03 kB
facebook-www/ReactDOM-profiling.modern.js+0.22%594.31 kB595.63 kB+0.22%104.07 kB104.29 kB
facebook-www/ReactDOMTesting-prod.classic.js+0.22%604.22 kB605.54 kB+0.21%107.51 kB107.74 kB
facebook-www/ReactDOM-profiling.classic.js+0.21%619.11 kB620.43 kB+0.22%108.10 kB108.33 kB
test_utils/ReactAllWarnings.jsDeleted64.24 kB0.00 kBDeleted16.03 kB0.00 kB

Generated by 🚫 dangerJS against 562f9c9

@acdlite
acdliteforce-pushed the automatically-reset-forms branch 2 times, most recently from 5e8fad4 to 41e6173CompareApril 10, 2024 00:38
@acdlite
acdlite marked this pull request as ready for review April 10, 2024 00:41

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should start a campaign for javascript64

@acdliteacdlite mentioned this pull request Apr 10, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right
in userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
@acdlite
acdliteforce-pushed the automatically-reset-forms branch from 41e6173 to 562f9c9CompareApril 10, 2024 04:04
const newResetState = {};
const resetStateHook: Hook = (formFiber.memoizedState.next: any);
const resetStateQueue = resetStateHook.queue;
dispatchSetState(formFiber, resetStateQueue, newResetState);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this actually have to be on the Fiber?

Can't it just be scheduled on the Root with a list of forms to reset when the root commits?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That way you don't need all the special commit phase stuff.

@acdliteacdliteApr 10, 2024

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm I'll need to think more about that, the scenario I had in mind was if the form is inside a Suspense boundary, the root could commit before the input's defaultValue had been updated. Usually this shouldn't happen because during a Transition we won't hide already visible forms, but during a popstate transition we might.

The <input form="myform"> case is interesting there, too.

@acdlite
acdlite merged commit 41950d1 into react:mainApr 10, 2024
acdlite added a commit that referenced this pull request Apr 10, 2024
Based on:
- #28804 ---
This sets adds a new ReactDOM export called requestFormReset, including
setting up the export and creating a method on the internal ReactDOM
dispatcher. It does not yet add any implementation.
Doing this in its own commit for review purposes.
The API itself will be explained in the next PR.
acdlite added a commit that referenced this pull request Apr 10, 2024
Based on:
- #28808
- #28804 ---
This adds a React DOM method called requestFormReset that schedules a
form reset to occur when the current transition completes.
Internally, it's the same method that's called automatically whenever a
form action is submitted. It only affects uncontrolled form inputs. See
#28804 for details.
The reason for the public API is so UI libraries can implement their own
action-based APIs and maintain the form-resetting behavior, something
like this:
```js
function onSubmit(event) {
// Disable default form submission behavior
event.preventDefault();
const form = event.target;
startTransition(async () => {
// Request the form to reset once the action
// has completed
requestFormReset(form);
// Call the user-provided action prop
await action(new FormData(form));
})
}
```
github-actionsBot pushed a commit that referenced this pull request Apr 10, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right in
userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
DiffTrain build for [41950d1](41950d1)
github-actionsBot pushed a commit that referenced this pull request Apr 10, 2024
Based on:
- #28804
---
This sets adds a new ReactDOM export called requestFormReset, including
setting up the export and creating a method on the internal ReactDOM
dispatcher. It does not yet add any implementation.
Doing this in its own commit for review purposes.
The API itself will be explained in the next PR.
DiffTrain build for [374b5d2](374b5d2)
github-actionsBot pushed a commit that referenced this pull request Apr 10, 2024
Based on:
- #28808
- #28804
---
This adds a React DOM method called requestFormReset that schedules a
form reset to occur when the current transition completes.
Internally, it's the same method that's called automatically whenever a
form action is submitted. It only affects uncontrolled form inputs. See
#28804 for details.
The reason for the public API is so UI libraries can implement their own
action-based APIs and maintain the form-resetting behavior, something
like this:
```js
function onSubmit(event) {
// Disable default form submission behavior
event.preventDefault();
const form = event.target;
startTransition(async () => {
// Request the form to reset once the action
// has completed
requestFormReset(form);
// Call the user-provided action prop
await action(new FormData(form));
})
}
```
DiffTrain build for [da69b6a](da69b6a)
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right in
userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
Based on:
- #28804 ---
This sets adds a new ReactDOM export called requestFormReset, including
setting up the export and creating a method on the internal ReactDOM
dispatcher. It does not yet add any implementation.
Doing this in its own commit for review purposes.
The API itself will be explained in the next PR.
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
Based on:
- #28808
- #28804 ---
This adds a React DOM method called requestFormReset that schedules a
form reset to occur when the current transition completes.
Internally, it's the same method that's called automatically whenever a
form action is submitted. It only affects uncontrolled form inputs. See
#28804 for details.
The reason for the public API is so UI libraries can implement their own
action-based APIs and maintain the form-resetting behavior, something
like this:
```js
function onSubmit(event) {
// Disable default form submission behavior
event.preventDefault();
const form = event.target;
startTransition(async () => {
// Request the form to reset once the action
// has completed
requestFormReset(form);
// Call the user-provided action prop
await action(new FormData(form));
})
}
```
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right in
userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
Based on:
- #28804 ---
This sets adds a new ReactDOM export called requestFormReset, including
setting up the export and creating a method on the internal ReactDOM
dispatcher. It does not yet add any implementation.
Doing this in its own commit for review purposes.
The API itself will be explained in the next PR.
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
Based on:
- #28808
- #28804 ---
This adds a React DOM method called requestFormReset that schedules a
form reset to occur when the current transition completes.
Internally, it's the same method that's called automatically whenever a
form action is submitted. It only affects uncontrolled form inputs. See
#28804 for details.
The reason for the public API is so UI libraries can implement their own
action-based APIs and maintain the form-resetting behavior, something
like this:
```js
function onSubmit(event) {
// Disable default form submission behavior
event.preventDefault();
const form = event.target;
startTransition(async () => {
// Request the form to reset once the action
// has completed
requestFormReset(form);
// Call the user-provided action prop
await action(new FormData(form));
})
}
```
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right in
userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
Based on:
- react#28804 ---
This sets adds a new ReactDOM export called requestFormReset, including
setting up the export and creating a method on the internal ReactDOM
dispatcher. It does not yet add any implementation.
Doing this in its own commit for review purposes.
The API itself will be explained in the next PR.
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
Based on:
- react#28808
- react#28804 ---
This adds a React DOM method called requestFormReset that schedules a
form reset to occur when the current transition completes.
Internally, it's the same method that's called automatically whenever a
form action is submitted. It only affects uncontrolled form inputs. See
react#28804 for details.
The reason for the public API is so UI libraries can implement their own
action-based APIs and maintain the form-resetting behavior, something
like this:
```js
function onSubmit(event) {
// Disable default form submission behavior
event.preventDefault();
const form = event.target;
startTransition(async () => {
// Request the form to reset once the action
// has completed
requestFormReset(form);
// Call the user-provided action prop
await action(new FormData(form));
})
}
```
bigfootjon pushed a commit that referenced this pull request Apr 18, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right in
userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
DiffTrain build for commit 41950d1.
facebook-github-bot pushed a commit to react/react-native that referenced this pull request Apr 19, 2024
Summary:
This sync includes the changes from:
- D56103750
- [TODO] A shim for SECRET_INTERNALS
This sync includes the following changes:
- **[b5e5ce8](react/react@b5e5ce8e0 )**: Update ReactNativeTypes for root options (part 2) ([#28857](react/react#28857)) //<Ricky>//
- **[da6ba53](react/react@da6ba53b1 )**: [UMD] Remove umd builds ([#28735](react/react#28735)) //<Josh Story>//
- **[0c245df](react/react@0c245df1d )**: Complete the typo fix ([#28856](react/react#28856)) //<Sebastian Silbermann>//
- **[f82051d](react/react@f82051d7a )**: console test utils fix: match entire string, not just first letter ([#28855](react/react#28855)) //<Andrew Clark>//
- **[4ca20fd](react/react@4ca20fd36 )**: Test top level fragment inside lazy semantics ([#28852](react/react#28852)) //<Sebastian Markbåge>//
- **[c0cf7c6](react/react@c0cf7c696 )**: Promote ASYNC_ITERATOR symbol to React Symbols ([#28851](react/react#28851)) //<Sebastian Markbåge>//
- **[657428a](react/react@657428a9e )**: Add ReactNativeTypes for root options ([#28850](react/react#28850)) //<Ricky>//
- **[7909d8e](react/react@7909d8eab )**: [Flight] Encode ReadableStream and AsyncIterables ([#28847](react/react#28847)) //<Sebastian Markbåge>//
- **[13eb61d](react/react@13eb61d05 )**: Move enableUseDeferredValueInitialArg to canary ([#28818](react/react#28818)) //<Andrew Clark>//
- **[8afa144](react/react@8afa144bd )**: Enable flag disableClientCache ([#28846](react/react#28846)) //<Jan Kassens>//
- **[734956a](react/react@734956ace )**: Devtools: Add support for useFormStatus ([#28413](react/react#28413)) //<Sebastian Silbermann>//
- **[17e920c](react/react@17e920c00 )**: [Flight Reply] Encode Typed Arrays and Blobs ([#28819](react/react#28819)) //<Sebastian Markbåge>//
- **[0347fcd](react/react@0347fcd00 )**: Add on(Caught|Uncaught|Recoverable) opts to RN ([#28836](react/react#28836)) //<Ricky>//
- **[c113503](react/react@c113503ad )**: Flush direct streams in Bun ([#28837](react/react#28837)) //<Kenta Iwasaki>//
- **[9defcd5](react/react@9defcd56b )**: Remove redundant props assign ([#28829](react/react#28829)) //<Sebastian Silbermann>//
- **[ed40236](react/react@ed4023603 )**: Fix mistaken "react-server" condition ([#28835](react/react#28835)) //<Sebastian Markbåge>//
- **[c8a0350](react/react@c8a035036 )**: [Fizz] hoistables should never flush before the preamble ([#28802](react/react#28802)) //<Josh Story>//
- **[4f5c812](react/react@4f5c812a3 )**: DevTools: Rely on sourcemaps to compute hook name of built-in hooks in newer versions ([#28593](react/react#28593)) //<Sebastian Silbermann>//
- **[4354159](react/react@435415962 )**: Backwards compatibility for string refs on WWW ([#28826](react/react#28826)) //<Jack Pope>//
- **[608edcc](react/react@608edcc90 )**: [tests] add `assertConsole<method>Dev` helpers ([#28732](react/react#28732)) //<Ricky>//
- **[da69b6a](react/react@da69b6af9 )**: ReactDOM.requestFormReset ([#28809](react/react#28809)) //<Andrew Clark>//
- **[374b5d2](react/react@374b5d26c )**: Scaffolding for requestFormReset API ([#28808](react/react#28808)) //<Andrew Clark>//
- **[41950d1](react/react@41950d14a )**: Automatically reset forms after action finishes ([#28804](react/react#28804)) //<Andrew Clark>//
- **[dc6a7e0](react/react@dc6a7e01e )**: [Float] Don't preload images inside `<noscript>` ([#28815](react/react#28815)) //<Josh Story>//
- **[3f947b1](react/react@3f947b1b4 )**: [tests] Assert scheduler log empty in internalAct ([#28737](react/react#28737)) //<Ricky>//
- **[bf09089](react/react@bf09089f6 )**: Remove Scheduler.log from ReactSuspenseFuzz-test ([#28812](react/react#28812)) //<Ricky>//
- **[84cb3b4](react/react@84cb3b4cb )**: Hardcode disableIEWorkarounds for www ([#28811](react/react#28811)) //<Ricky>//
- **[2243b40](react/react@2243b40ab )**: [tests] assertLog before act in useEffectEvent ([#28763](react/react#28763)) //<Ricky>//
- **[dfc64c6](react/react@dfc64c6e3 )**: [tests] assertLog before act in ReactUse ([#28762](react/react#28762)) //<Ricky>//
- **[42eff4b](react/react@42eff4bc7 )**: [tests] Fix assertions not flushed before act ([#28745](react/react#28745)) //<Ricky>//
- **[ed3c65c](react/react@ed3c65caf )**: Warn if outdated JSX transform is detected ([#28781](react/react#28781)) //<Andrew Clark>//
- **[3f9e237](react/react@3f9e237a2 )**: Fix: Suspend while recovering from hydration error ([#28800](react/react#28800)) //<Andrew Clark>//
- **[7f5d25e](react/react@7f5d25e23 )**: Fix cloneElement using string ref w no owner ([#28797](react/react#28797)) //<Joseph Savona>//
- **[bf40b02](react/react@bf40b0244 )**: [Fizz] Stop publishing external-runtime to stable channel ([#28796](react/react#28796)) //<Josh Story>//
- **[7f93cb4](react/react@7f93cb41c )**: [DOM] Infer react-server entries bundles if not explicitly configured ([#28795](react/react#28795)) //<Josh Story>//
- **[f613165](react/react@f61316535 )**: Rename SECRET INTERNALS to `__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE` ([#28789](react/react#28789)) //<Sebastian Markbåge>//
- **[9644d20](react/react@9644d206e )**: Soften useFormState warning ([#28788](react/react#28788)) //<Ricky>//
- **[c771016](react/react@c771016e1 )**: Rename The Secret Export of Server Internals ([#28786](react/react#28786)) //<Sebastian Markbåge>//
- **[d50323e](react/react@d50323eb8 )**: Flatten ReactSharedInternals ([#28783](react/react#28783)) //<Sebastian Markbåge>//
- **[f62cf8c](react/react@f62cf8c62 )**: [Float] treat `props.async` in Float consistent with the rest of react-dom ([#26760](react/react#26760)) //<Josh Story>//
- **[dfd3d5a](react/react@dfd3d5af8 )**: Add support for transition{run,start,cancel} events ([#27345](react/react#27345)) //<Hugo Sales>//
- **[1f8327f](react/react@1f8327f83 )**: [Fiber] Use real event priority for hydration scheduling ([#28765](react/react#28765)) //<Josh Story>//
- **[97c90ed](react/react@97c90ed88 )**: [DOM] Shrink ReactDOMCurrentDispatcher method names ([#28770](react/react#28770)) //<Josh Story>//
- **[9007fdc](react/react@9007fdc8f )**: [DOM] Shrink ReactDOMSharedInternals source representation ([#28771](react/react#28771)) //<Josh Story>//
- **[14f50ad](react/react@14f50ad15 )**: [Flight] Allow lazily resolving outlined models ([#28780](react/react#28780)) //<Sebastian Markbåge>//
- **[4c12339](react/react@4c12339ce )**: [DOM] move `flushSync` out of the reconciler ([#28500](react/react#28500)) //<Josh Story>//
- **[8e1462e](react/react@8e1462e8c )**: [Fiber] Move updatePriority tracking to renderers ([#28751](react/react#28751)) //<Josh Story>//
- **[0b3b8a6](react/react@0b3b8a6a3 )**: jsx: Remove unnecessary hasOwnProperty check ([#28775](react/react#28775)) //<Andrew Clark>//
- **[2acfb7b](react/react@2acfb7b60 )**: [Flight] Support FormData from Server to Client ([#28754](react/react#28754)) //<Sebastian Markbåge>//
- **[d1547de](react/react@d1547defe )**: Fast JSX: Don't clone props object ([#28768](react/react#28768)) //<Andrew Clark>//
- **[bfd8da8](react/react@bfd8da807 )**: Make class prop resolution faster ([#28766](react/react#28766)) //<Andrew Clark>//
- **[cbb6f2b](react/react@cbb6f2b54 )**: [Flight] Support Blobs from Server to Client ([#28755](react/react#28755)) //<Sebastian Markbåge>//
- **[f33a6b6](react/react@f33a6b69c )**: Track Owner for Server Components in DEV ([#28753](react/react#28753)) //<Sebastian Markbåge>//
- **[e3ebcd5](react/react@e3ebcd54b )**: Move string ref coercion to JSX runtime ([#28473](react/react#28473)) //<Andrew Clark>//
- **[fd0da3e](react/react@fd0da3eef )**: Remove _owner field from JSX elements in prod if string refs are disabled ([#28739](react/react#28739)) //<Sebastian Markbåge>//
Changelog:
[General][Changed] - React Native sync for revisions 48b4ecc...b5e5ce8
jest_e2e[run_all_tests]
bypass-github-export-checks
Reviewed By: kassens
Differential Revision: D56251607
fbshipit-source-id: e16db2fa101fc7ed1e009158c76388206beabd5f
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA SignedReact Core TeamOpened by a member of the React Core Team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@acdlite@react-sizebot@sebmarkbage@gnoff@facebook-github-bot
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Automatically reset forms after action finishes - #28804

Merged
acdlite merged 1 commit into
react:mainfrom
acdlite:automatically-reset-forms
Apr 10, 2024
Merged

Automatically reset forms after action finishes#28804
acdlite merged 1 commit into
react:mainfrom
acdlite:automatically-reset-forms

Conversation

@acdlite

Copy link
Copy Markdown
Collaborator

This updates the behavior of form actions to automatically reset the form's uncontrolled inputs after the action finishes.

This is a frequent feature request for people using actions and it aligns the behavior of client-side form submissions more closely with MPA form submissions.

It has no impact on controlled form inputs. It's the same as if you called form.reset() manually, except React handles the timing of when the reset happens, which is tricky/impossible to get exactly right in userspace.

The reset shouldn't happen until the UI has updated with the result of the action. So, resetting inside the action is too early.

Resetting in useEffect is better, but it's later than ideal because any effects that run before it will observe the state of the form before it's been reset.

It needs to happen in the mutation phase of the transition. More specifically, after all the DOM mutations caused by the transition have been applied. That way the defaultValue of the inputs are updated before the values are reset. The idea is that the defaultValue represents the current, canonical value sent by the server.

Note: this change has no effect on form submissions that aren't triggered by an action.

@facebook-github-botfacebook-github-bot added CLA Signed React Core Team Opened by a member of the React Core Team labels Apr 10, 2024
@react-sizebot

react-sizebot commented Apr 10, 2024

Copy link
Copy Markdown

Comparing: ed3c65c...562f9c9

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name+/-BaseCurrent+/- gzipBase gzipCurrent gzip
oss-stable/react-dom/cjs/react-dom.production.min.js+0.27%168.12 kB168.57 kB+0.24%52.72 kB52.85 kB
oss-experimental/react-dom/cjs/react-dom.production.min.js+0.26%169.92 kB170.37 kB+0.20%53.26 kB53.37 kB
facebook-www/ReactDOM-prod.classic.js+0.22%589.57 kB590.89 kB+0.22%103.80 kB104.03 kB
facebook-www/ReactDOM-prod.modern.js+0.23%565.41 kB566.73 kB+0.23%99.93 kB100.16 kB
test_utils/ReactAllWarnings.jsDeleted64.24 kB0.00 kBDeleted16.03 kB0.00 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name+/-BaseCurrent+/- gzipBase gzipCurrent gzip
oss-stable-semver/react-reconciler/cjs/react-reconciler.production.js+0.49%665.84 kB669.08 kB+0.51%146.23 kB146.97 kB
oss-stable/react-reconciler/cjs/react-reconciler.production.js+0.49%665.86 kB669.11 kB+0.51%146.26 kB147.01 kB
oss-experimental/react-reconciler/cjs/react-reconciler.production.js+0.48%672.88 kB676.12 kB+0.53%147.79 kB148.57 kB
oss-stable-semver/react-reconciler/cjs/react-reconciler.development.js+0.48%908.86 kB913.24 kB+0.53%195.30 kB196.34 kB
oss-stable/react-reconciler/cjs/react-reconciler.development.js+0.48%908.89 kB913.27 kB+0.53%195.33 kB196.37 kB
oss-experimental/react-reconciler/cjs/react-reconciler.development.js+0.48%918.20 kB922.58 kB+0.53%197.14 kB198.19 kB
oss-stable-semver/react-reconciler/cjs/react-reconciler.profiling.js+0.46%705.86 kB709.10 kB+0.50%153.52 kB154.29 kB
oss-stable/react-reconciler/cjs/react-reconciler.profiling.js+0.46%705.89 kB709.13 kB+0.50%153.55 kB154.31 kB
oss-experimental/react-reconciler/cjs/react-reconciler.profiling.js+0.46%712.90 kB716.14 kB+0.49%155.11 kB155.88 kB
oss-stable-semver/react-reconciler/cjs/react-reconciler.production.min.js+0.43%108.56 kB109.03 kB+0.39%33.85 kB33.98 kB
oss-stable/react-reconciler/cjs/react-reconciler.production.min.js+0.43%108.59 kB109.06 kB+0.39%33.87 kB34.00 kB
oss-experimental/react-reconciler/cjs/react-reconciler.production.min.js+0.42%110.35 kB110.82 kB+0.37%34.47 kB34.60 kB
oss-stable-semver/react-reconciler/cjs/react-reconciler.profiling.min.js+0.40%117.42 kB117.89 kB+0.32%36.09 kB36.21 kB
oss-stable/react-reconciler/cjs/react-reconciler.profiling.min.js+0.40%117.45 kB117.92 kB+0.33%36.11 kB36.23 kB
oss-experimental/react-reconciler/cjs/react-reconciler.profiling.min.js+0.39%119.21 kB119.67 kB+0.41%36.65 kB36.80 kB
oss-stable-semver/react-dom/cjs/react-dom.production.js+0.35%919.85 kB923.06 kB+0.37%206.89 kB207.65 kB
oss-stable/react-dom/cjs/react-dom.production.js+0.35%919.87 kB923.08 kB+0.37%206.92 kB207.68 kB
oss-experimental/react-dom/cjs/react-dom.production.js+0.35%926.94 kB930.15 kB+0.37%208.43 kB209.20 kB
oss-experimental/react-dom/cjs/react-dom-unstable_testing.production.js+0.34%945.18 kB948.39 kB+0.36%212.95 kB213.71 kB
oss-stable-semver/react-dom/cjs/react-dom.development.js+0.34%1,293.34 kB1,297.68 kB+0.37%286.49 kB287.55 kB
oss-stable/react-dom/cjs/react-dom.development.js+0.34%1,293.36 kB1,297.71 kB+0.37%286.52 kB287.58 kB
oss-stable-semver/react-dom/umd/react-dom.development.js+0.34%1,356.09 kB1,360.63 kB+0.38%289.40 kB290.49 kB
oss-stable/react-dom/umd/react-dom.development.js+0.34%1,356.12 kB1,360.66 kB+0.38%289.43 kB290.52 kB
oss-stable-semver/react-dom/cjs/react-dom.profiling.js+0.33%960.46 kB963.67 kB+0.35%214.16 kB214.92 kB
oss-stable/react-dom/cjs/react-dom.profiling.js+0.33%960.48 kB963.69 kB+0.35%214.19 kB214.95 kB
oss-experimental/react-dom/cjs/react-dom.development.js+0.33%1,302.73 kB1,307.08 kB+0.37%288.32 kB289.39 kB
oss-experimental/react-dom/umd/react-dom.development.js+0.33%1,365.97 kB1,370.51 kB+0.36%291.21 kB292.26 kB
oss-experimental/react-dom/cjs/react-dom.profiling.js+0.33%967.55 kB970.76 kB+0.35%215.71 kB216.46 kB
oss-experimental/react-dom/cjs/react-dom-unstable_testing.development.js+0.33%1,321.15 kB1,325.50 kB+0.37%292.77 kB293.84 kB
facebook-www/ReactDOM-dev.modern.js+0.30%1,621.20 kB1,626.01 kB+0.34%322.53 kB323.63 kB
facebook-www/ReactDOMTesting-dev.modern.js+0.29%1,644.60 kB1,649.41 kB+0.34%327.14 kB328.26 kB
facebook-www/ReactDOM-dev.classic.js+0.29%1,673.24 kB1,678.05 kB+0.34%331.38 kB332.50 kB
facebook-www/ReactDOMTesting-dev.classic.js+0.28%1,697.92 kB1,702.73 kB+0.33%336.19 kB337.31 kB
oss-stable-semver/react-dom/umd/react-dom.production.min.js+0.27%167.79 kB168.24 kB+0.28%53.04 kB53.19 kB
oss-stable/react-dom/umd/react-dom.production.min.js+0.27%167.87 kB168.32 kB+0.28%53.07 kB53.22 kB
oss-stable-semver/react-dom/cjs/react-dom.production.min.js+0.27%168.04 kB168.49 kB+0.24%52.69 kB52.82 kB
oss-stable/react-dom/cjs/react-dom.production.min.js+0.27%168.12 kB168.57 kB+0.24%52.72 kB52.85 kB
oss-experimental/react-dom/umd/react-dom.production.min.js+0.27%169.67 kB170.13 kB+0.25%53.70 kB53.83 kB
oss-experimental/react-dom/cjs/react-dom.production.min.js+0.26%169.92 kB170.37 kB+0.20%53.26 kB53.37 kB
oss-stable-semver/react-dom/umd/react-dom.profiling.min.js+0.25%176.63 kB177.08 kB+0.21%55.45 kB55.56 kB
oss-stable/react-dom/umd/react-dom.profiling.min.js+0.25%176.71 kB177.16 kB+0.21%55.47 kB55.59 kB
oss-experimental/react-dom/cjs/react-dom-unstable_testing.production.min.js+0.25%176.86 kB177.31 kB+0.20%55.85 kB55.97 kB
oss-stable-semver/react-dom/cjs/react-dom.profiling.min.js+0.25%177.32 kB177.77 kB+0.22%55.14 kB55.26 kB
oss-stable/react-dom/cjs/react-dom.profiling.min.js+0.25%177.40 kB177.85 kB+0.22%55.16 kB55.28 kB
oss-experimental/react-dom/umd/react-dom.profiling.min.js+0.25%178.51 kB178.96 kB+0.25%56.01 kB56.15 kB
oss-experimental/react-dom/cjs/react-dom.profiling.min.js+0.25%179.21 kB179.66 kB+0.25%55.71 kB55.85 kB
facebook-www/ReactDOM-prod.modern.js+0.23%565.41 kB566.73 kB+0.23%99.93 kB100.16 kB
facebook-www/ReactDOMTesting-prod.modern.js+0.23%581.36 kB582.67 kB+0.22%103.88 kB104.11 kB
facebook-www/ReactDOM-prod.classic.js+0.22%589.57 kB590.89 kB+0.22%103.80 kB104.03 kB
facebook-www/ReactDOM-profiling.modern.js+0.22%594.31 kB595.63 kB+0.22%104.07 kB104.29 kB
facebook-www/ReactDOMTesting-prod.classic.js+0.22%604.22 kB605.54 kB+0.21%107.51 kB107.74 kB
facebook-www/ReactDOM-profiling.classic.js+0.21%619.11 kB620.43 kB+0.22%108.10 kB108.33 kB
test_utils/ReactAllWarnings.jsDeleted64.24 kB0.00 kBDeleted16.03 kB0.00 kB

Generated by 🚫 dangerJS against 562f9c9

@acdlite
acdliteforce-pushed the automatically-reset-forms branch 2 times, most recently from 5e8fad4 to 41e6173CompareApril 10, 2024 00:38
@acdlite
acdlite marked this pull request as ready for review April 10, 2024 00:41

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should start a campaign for javascript64

@acdliteacdlite mentioned this pull request Apr 10, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right
in userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
@acdlite
acdliteforce-pushed the automatically-reset-forms branch from 41e6173 to 562f9c9CompareApril 10, 2024 04:04
const newResetState = {};
const resetStateHook: Hook = (formFiber.memoizedState.next: any);
const resetStateQueue = resetStateHook.queue;
dispatchSetState(formFiber, resetStateQueue, newResetState);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this actually have to be on the Fiber?

Can't it just be scheduled on the Root with a list of forms to reset when the root commits?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That way you don't need all the special commit phase stuff.

@acdliteacdliteApr 10, 2024

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm I'll need to think more about that, the scenario I had in mind was if the form is inside a Suspense boundary, the root could commit before the input's defaultValue had been updated. Usually this shouldn't happen because during a Transition we won't hide already visible forms, but during a popstate transition we might.

The <input form="myform"> case is interesting there, too.

@acdlite
acdlite merged commit 41950d1 into react:mainApr 10, 2024
acdlite added a commit that referenced this pull request Apr 10, 2024
Based on:
- #28804 ---
This sets adds a new ReactDOM export called requestFormReset, including
setting up the export and creating a method on the internal ReactDOM
dispatcher. It does not yet add any implementation.
Doing this in its own commit for review purposes.
The API itself will be explained in the next PR.
acdlite added a commit that referenced this pull request Apr 10, 2024
Based on:
- #28808
- #28804 ---
This adds a React DOM method called requestFormReset that schedules a
form reset to occur when the current transition completes.
Internally, it's the same method that's called automatically whenever a
form action is submitted. It only affects uncontrolled form inputs. See
#28804 for details.
The reason for the public API is so UI libraries can implement their own
action-based APIs and maintain the form-resetting behavior, something
like this:
```js
function onSubmit(event) {
// Disable default form submission behavior
event.preventDefault();
const form = event.target;
startTransition(async () => {
// Request the form to reset once the action
// has completed
requestFormReset(form);
// Call the user-provided action prop
await action(new FormData(form));
})
}
```
github-actionsBot pushed a commit that referenced this pull request Apr 10, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right in
userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
DiffTrain build for [41950d1](41950d1)
github-actionsBot pushed a commit that referenced this pull request Apr 10, 2024
Based on:
- #28804
---
This sets adds a new ReactDOM export called requestFormReset, including
setting up the export and creating a method on the internal ReactDOM
dispatcher. It does not yet add any implementation.
Doing this in its own commit for review purposes.
The API itself will be explained in the next PR.
DiffTrain build for [374b5d2](374b5d2)
github-actionsBot pushed a commit that referenced this pull request Apr 10, 2024
Based on:
- #28808
- #28804
---
This adds a React DOM method called requestFormReset that schedules a
form reset to occur when the current transition completes.
Internally, it's the same method that's called automatically whenever a
form action is submitted. It only affects uncontrolled form inputs. See
#28804 for details.
The reason for the public API is so UI libraries can implement their own
action-based APIs and maintain the form-resetting behavior, something
like this:
```js
function onSubmit(event) {
// Disable default form submission behavior
event.preventDefault();
const form = event.target;
startTransition(async () => {
// Request the form to reset once the action
// has completed
requestFormReset(form);
// Call the user-provided action prop
await action(new FormData(form));
})
}
```
DiffTrain build for [da69b6a](da69b6a)
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right in
userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
Based on:
- #28804 ---
This sets adds a new ReactDOM export called requestFormReset, including
setting up the export and creating a method on the internal ReactDOM
dispatcher. It does not yet add any implementation.
Doing this in its own commit for review purposes.
The API itself will be explained in the next PR.
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
Based on:
- #28808
- #28804 ---
This adds a React DOM method called requestFormReset that schedules a
form reset to occur when the current transition completes.
Internally, it's the same method that's called automatically whenever a
form action is submitted. It only affects uncontrolled form inputs. See
#28804 for details.
The reason for the public API is so UI libraries can implement their own
action-based APIs and maintain the form-resetting behavior, something
like this:
```js
function onSubmit(event) {
// Disable default form submission behavior
event.preventDefault();
const form = event.target;
startTransition(async () => {
// Request the form to reset once the action
// has completed
requestFormReset(form);
// Call the user-provided action prop
await action(new FormData(form));
})
}
```
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right in
userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
Based on:
- #28804 ---
This sets adds a new ReactDOM export called requestFormReset, including
setting up the export and creating a method on the internal ReactDOM
dispatcher. It does not yet add any implementation.
Doing this in its own commit for review purposes.
The API itself will be explained in the next PR.
rickhanlonii pushed a commit that referenced this pull request Apr 11, 2024
Based on:
- #28808
- #28804 ---
This adds a React DOM method called requestFormReset that schedules a
form reset to occur when the current transition completes.
Internally, it's the same method that's called automatically whenever a
form action is submitted. It only affects uncontrolled form inputs. See
#28804 for details.
The reason for the public API is so UI libraries can implement their own
action-based APIs and maintain the form-resetting behavior, something
like this:
```js
function onSubmit(event) {
// Disable default form submission behavior
event.preventDefault();
const form = event.target;
startTransition(async () => {
// Request the form to reset once the action
// has completed
requestFormReset(form);
// Call the user-provided action prop
await action(new FormData(form));
})
}
```
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right in
userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
Based on:
- react#28804 ---
This sets adds a new ReactDOM export called requestFormReset, including
setting up the export and creating a method on the internal ReactDOM
dispatcher. It does not yet add any implementation.
Doing this in its own commit for review purposes.
The API itself will be explained in the next PR.
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
Based on:
- react#28808
- react#28804 ---
This adds a React DOM method called requestFormReset that schedules a
form reset to occur when the current transition completes.
Internally, it's the same method that's called automatically whenever a
form action is submitted. It only affects uncontrolled form inputs. See
react#28804 for details.
The reason for the public API is so UI libraries can implement their own
action-based APIs and maintain the form-resetting behavior, something
like this:
```js
function onSubmit(event) {
// Disable default form submission behavior
event.preventDefault();
const form = event.target;
startTransition(async () => {
// Request the form to reset once the action
// has completed
requestFormReset(form);
// Call the user-provided action prop
await action(new FormData(form));
})
}
```
bigfootjon pushed a commit that referenced this pull request Apr 18, 2024
This updates the behavior of form actions to automatically reset the
form's uncontrolled inputs after the action finishes.
This is a frequent feature request for people using actions and it
aligns the behavior of client-side form submissions more closely with
MPA form submissions.
It has no impact on controlled form inputs. It's the same as if you
called `form.reset()` manually, except React handles the timing of when
the reset happens, which is tricky/impossible to get exactly right in
userspace.
The reset shouldn't happen until the UI has updated with the result of
the action. So, resetting inside the action is too early.
Resetting in `useEffect` is better, but it's later than ideal because
any effects that run before it will observe the state of the form before
it's been reset.
It needs to happen in the mutation phase of the transition. More
specifically, after all the DOM mutations caused by the transition have
been applied. That way the `defaultValue` of the inputs are updated
before the values are reset. The idea is that the `defaultValue`
represents the current, canonical value sent by the server.
Note: this change has no effect on form submissions that aren't
triggered by an action.
DiffTrain build for commit 41950d1.
facebook-github-bot pushed a commit to react/react-native that referenced this pull request Apr 19, 2024
Summary:
This sync includes the changes from:
- D56103750
- [TODO] A shim for SECRET_INTERNALS
This sync includes the following changes:
- **[b5e5ce8](react/react@b5e5ce8e0 )**: Update ReactNativeTypes for root options (part 2) ([#28857](react/react#28857)) //<Ricky>//
- **[da6ba53](react/react@da6ba53b1 )**: [UMD] Remove umd builds ([#28735](react/react#28735)) //<Josh Story>//
- **[0c245df](react/react@0c245df1d )**: Complete the typo fix ([#28856](react/react#28856)) //<Sebastian Silbermann>//
- **[f82051d](react/react@f82051d7a )**: console test utils fix: match entire string, not just first letter ([#28855](react/react#28855)) //<Andrew Clark>//
- **[4ca20fd](react/react@4ca20fd36 )**: Test top level fragment inside lazy semantics ([#28852](react/react#28852)) //<Sebastian Markbåge>//
- **[c0cf7c6](react/react@c0cf7c696 )**: Promote ASYNC_ITERATOR symbol to React Symbols ([#28851](react/react#28851)) //<Sebastian Markbåge>//
- **[657428a](react/react@657428a9e )**: Add ReactNativeTypes for root options ([#28850](react/react#28850)) //<Ricky>//
- **[7909d8e](react/react@7909d8eab )**: [Flight] Encode ReadableStream and AsyncIterables ([#28847](react/react#28847)) //<Sebastian Markbåge>//
- **[13eb61d](react/react@13eb61d05 )**: Move enableUseDeferredValueInitialArg to canary ([#28818](react/react#28818)) //<Andrew Clark>//
- **[8afa144](react/react@8afa144bd )**: Enable flag disableClientCache ([#28846](react/react#28846)) //<Jan Kassens>//
- **[734956a](react/react@734956ace )**: Devtools: Add support for useFormStatus ([#28413](react/react#28413)) //<Sebastian Silbermann>//
- **[17e920c](react/react@17e920c00 )**: [Flight Reply] Encode Typed Arrays and Blobs ([#28819](react/react#28819)) //<Sebastian Markbåge>//
- **[0347fcd](react/react@0347fcd00 )**: Add on(Caught|Uncaught|Recoverable) opts to RN ([#28836](react/react#28836)) //<Ricky>//
- **[c113503](react/react@c113503ad )**: Flush direct streams in Bun ([#28837](react/react#28837)) //<Kenta Iwasaki>//
- **[9defcd5](react/react@9defcd56b )**: Remove redundant props assign ([#28829](react/react#28829)) //<Sebastian Silbermann>//
- **[ed40236](react/react@ed4023603 )**: Fix mistaken "react-server" condition ([#28835](react/react#28835)) //<Sebastian Markbåge>//
- **[c8a0350](react/react@c8a035036 )**: [Fizz] hoistables should never flush before the preamble ([#28802](react/react#28802)) //<Josh Story>//
- **[4f5c812](react/react@4f5c812a3 )**: DevTools: Rely on sourcemaps to compute hook name of built-in hooks in newer versions ([#28593](react/react#28593)) //<Sebastian Silbermann>//
- **[4354159](react/react@435415962 )**: Backwards compatibility for string refs on WWW ([#28826](react/react#28826)) //<Jack Pope>//
- **[608edcc](react/react@608edcc90 )**: [tests] add `assertConsole<method>Dev` helpers ([#28732](react/react#28732)) //<Ricky>//
- **[da69b6a](react/react@da69b6af9 )**: ReactDOM.requestFormReset ([#28809](react/react#28809)) //<Andrew Clark>//
- **[374b5d2](react/react@374b5d26c )**: Scaffolding for requestFormReset API ([#28808](react/react#28808)) //<Andrew Clark>//
- **[41950d1](react/react@41950d14a )**: Automatically reset forms after action finishes ([#28804](react/react#28804)) //<Andrew Clark>//
- **[dc6a7e0](react/react@dc6a7e01e )**: [Float] Don't preload images inside `<noscript>` ([#28815](react/react#28815)) //<Josh Story>//
- **[3f947b1](react/react@3f947b1b4 )**: [tests] Assert scheduler log empty in internalAct ([#28737](react/react#28737)) //<Ricky>//
- **[bf09089](react/react@bf09089f6 )**: Remove Scheduler.log from ReactSuspenseFuzz-test ([#28812](react/react#28812)) //<Ricky>//
- **[84cb3b4](react/react@84cb3b4cb )**: Hardcode disableIEWorkarounds for www ([#28811](react/react#28811)) //<Ricky>//
- **[2243b40](react/react@2243b40ab )**: [tests] assertLog before act in useEffectEvent ([#28763](react/react#28763)) //<Ricky>//
- **[dfc64c6](react/react@dfc64c6e3 )**: [tests] assertLog before act in ReactUse ([#28762](react/react#28762)) //<Ricky>//
- **[42eff4b](react/react@42eff4bc7 )**: [tests] Fix assertions not flushed before act ([#28745](react/react#28745)) //<Ricky>//
- **[ed3c65c](react/react@ed3c65caf )**: Warn if outdated JSX transform is detected ([#28781](react/react#28781)) //<Andrew Clark>//
- **[3f9e237](react/react@3f9e237a2 )**: Fix: Suspend while recovering from hydration error ([#28800](react/react#28800)) //<Andrew Clark>//
- **[7f5d25e](react/react@7f5d25e23 )**: Fix cloneElement using string ref w no owner ([#28797](react/react#28797)) //<Joseph Savona>//
- **[bf40b02](react/react@bf40b0244 )**: [Fizz] Stop publishing external-runtime to stable channel ([#28796](react/react#28796)) //<Josh Story>//
- **[7f93cb4](react/react@7f93cb41c )**: [DOM] Infer react-server entries bundles if not explicitly configured ([#28795](react/react#28795)) //<Josh Story>//
- **[f613165](react/react@f61316535 )**: Rename SECRET INTERNALS to `__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE` ([#28789](react/react#28789)) //<Sebastian Markbåge>//
- **[9644d20](react/react@9644d206e )**: Soften useFormState warning ([#28788](react/react#28788)) //<Ricky>//
- **[c771016](react/react@c771016e1 )**: Rename The Secret Export of Server Internals ([#28786](react/react#28786)) //<Sebastian Markbåge>//
- **[d50323e](react/react@d50323eb8 )**: Flatten ReactSharedInternals ([#28783](react/react#28783)) //<Sebastian Markbåge>//
- **[f62cf8c](react/react@f62cf8c62 )**: [Float] treat `props.async` in Float consistent with the rest of react-dom ([#26760](react/react#26760)) //<Josh Story>//
- **[dfd3d5a](react/react@dfd3d5af8 )**: Add support for transition{run,start,cancel} events ([#27345](react/react#27345)) //<Hugo Sales>//
- **[1f8327f](react/react@1f8327f83 )**: [Fiber] Use real event priority for hydration scheduling ([#28765](react/react#28765)) //<Josh Story>//
- **[97c90ed](react/react@97c90ed88 )**: [DOM] Shrink ReactDOMCurrentDispatcher method names ([#28770](react/react#28770)) //<Josh Story>//
- **[9007fdc](react/react@9007fdc8f )**: [DOM] Shrink ReactDOMSharedInternals source representation ([#28771](react/react#28771)) //<Josh Story>//
- **[14f50ad](react/react@14f50ad15 )**: [Flight] Allow lazily resolving outlined models ([#28780](react/react#28780)) //<Sebastian Markbåge>//
- **[4c12339](react/react@4c12339ce )**: [DOM] move `flushSync` out of the reconciler ([#28500](react/react#28500)) //<Josh Story>//
- **[8e1462e](react/react@8e1462e8c )**: [Fiber] Move updatePriority tracking to renderers ([#28751](react/react#28751)) //<Josh Story>//
- **[0b3b8a6](react/react@0b3b8a6a3 )**: jsx: Remove unnecessary hasOwnProperty check ([#28775](react/react#28775)) //<Andrew Clark>//
- **[2acfb7b](react/react@2acfb7b60 )**: [Flight] Support FormData from Server to Client ([#28754](react/react#28754)) //<Sebastian Markbåge>//
- **[d1547de](react/react@d1547defe )**: Fast JSX: Don't clone props object ([#28768](react/react#28768)) //<Andrew Clark>//
- **[bfd8da8](react/react@bfd8da807 )**: Make class prop resolution faster ([#28766](react/react#28766)) //<Andrew Clark>//
- **[cbb6f2b](react/react@cbb6f2b54 )**: [Flight] Support Blobs from Server to Client ([#28755](react/react#28755)) //<Sebastian Markbåge>//
- **[f33a6b6](react/react@f33a6b69c )**: Track Owner for Server Components in DEV ([#28753](react/react#28753)) //<Sebastian Markbåge>//
- **[e3ebcd5](react/react@e3ebcd54b )**: Move string ref coercion to JSX runtime ([#28473](react/react#28473)) //<Andrew Clark>//
- **[fd0da3e](react/react@fd0da3eef )**: Remove _owner field from JSX elements in prod if string refs are disabled ([#28739](react/react#28739)) //<Sebastian Markbåge>//
Changelog:
[General][Changed] - React Native sync for revisions 48b4ecc...b5e5ce8
jest_e2e[run_all_tests]
bypass-github-export-checks
Reviewed By: kassens
Differential Revision: D56251607
fbshipit-source-id: e16db2fa101fc7ed1e009158c76388206beabd5f
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA SignedReact Core TeamOpened by a member of the React Core Team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@acdlite@react-sizebot@sebmarkbage@gnoff@facebook-github-bot