Skip to content

Enhance form documentation for form default reset behavior#8512

Open
MaxwellCohen wants to merge 12 commits into
reactjs:mainfrom
MaxwellCohen:feat/8397/disabling-default-form-reset
Open

Enhance form documentation for form default reset behavior#8512
MaxwellCohen wants to merge 12 commits into
reactjs:mainfrom
MaxwellCohen:feat/8397/disabling-default-form-reset

Conversation

@MaxwellCohen

Copy link
Copy Markdown
Contributor

Summary

Documents React’s default form-reset behavior when using the function action / formAction props, and explains how to preserve field values when you don’t want that reset. Applying @rickhanlonii's feedback from #7795 and building off of work @aurorascharff recentlly did.

  • Adds default reset behavior in Caveats, the action prop section, and a new Troubleshooting entry (“Why does my form reset when I use an action?”). React resets uncontrolled fields after a successful action, matching browser <form action="..."> behavior (including before JS loads).
  • Adds “Preserve form values after submission” with a Sandpack example: call e.preventDefault() in onSubmit, then run the action manually inside useTransition while keeping the action prop for progressive enhancement.
  • Adds a DeepDive for finer control: requestFormReset from react-dom, and returning submitted FormData from server actions to restore values via defaultValue (with useActionState).
  • Updates the multiple-submission-types example to a draft/publish scenario that shows how controlled state and key/defaultValue keep textarea content after “Save draft.”

Closes #8397

Alternative to #7795 and #8465

@github-actions

Copy link
Copy Markdown

Size changes

Details

📦 Next.js Bundle Analysis for react-dev

This analysis was generated by the Next.js Bundle Analysis action. 🤖

This PR introduced no changes to the JavaScript bundle! 🙌

@MaxwellCohen MaxwellCohen marked this pull request as ready for review June 29, 2026 19:09
@aurorascharff

Copy link
Copy Markdown
Collaborator

Going to dig a bit into the current behavior of this, so might take some time to review! Thank you!

@aurorascharff aurorascharff requested a review from gaearon July 1, 2026 17:21
…ction` prop and its behavior:

- including the handling of `FormData`,
- the necessity of `name` attributes,
- the advantages of using a function over a URL.
- removed redundant information about `e.preventDefault()` for the `action` prop.
Give each input a `name` attribute so its value is included in `FormData`. You can use [uncontrolled](/reference/react-dom/components/input#reading-the-input-values-when-submitting-a-form) inputs instead of controlled `value`/`onChange` pairs, and you don't need an `onSubmit` handler or `e.preventDefault()`.

Pass a function to the `action` prop of form to run the function when the form is submitted. [`formData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData) will be passed to the function as an argument so you can access the data submitted by the form. This differs from the conventional [HTML action](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form#action), which only accepts URLs. Unlike `onSubmit`, an `action` runs in a [Transition](/reference/react/useTransition) and calling `e.preventDefault()` isn't needed. After the `action` function succeeds, all uncontrolled field elements in the form are reset.
This extends the [HTML `action` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form#action), which only accepts a URL, to also accept a function. Because the form stays a native HTML form, it can be submitted before JavaScript loads; with a [Server Function](/reference/rsc/server-functions), it works without JavaScript enabled.

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.

ecause the form stays a native HTML form, it can be submitted before JavaScript loads; with a [Server Function](/reference/rsc/server-functions), it works without JavaScript enabled

this part is a bit unclear and hard to parse!

@MaxwellCohen MaxwellCohen Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Great point. When I read it 3 times last week, it seemed so clear ;) now it is not

udpate in b341728

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.

I feel you on that 😂


* Runs the submission function in a [Transition](/reference/react/useTransition).
* Tracks pending state so child components can read it with [`useFormStatus`](/reference/react-dom/hooks/useFormStatus).
* Sends thrown errors to the nearest error boundary.

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.

Not sure if "sends" is the right terminology for this 🤔

@MaxwellCohen MaxwellCohen Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good point! I will reword!

see b341728

* Runs the submission function in a [Transition](/reference/react/useTransition).
* Tracks pending state so child components can read it with [`useFormStatus`](/reference/react-dom/hooks/useFormStatus).
* Sends thrown errors to the nearest error boundary.
* Works with [`useActionState`](/reference/react/useActionState) and [`useOptimistic`](/reference/react/useOptimistic) for form state and optimistic UI.

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.

This bullet seems out of place in its framing, since the intro to the list is When you pass a function to action, React: but here "works" is not answering that question!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

is b341728 better

### Display a pending state during form submission {/*display-a-pending-state-during-form-submission*/}
### Preserving form values after submission {/*preserve-form-values-after-submission*/}

The browser clears a form's input state on submit. A URL `action` follows this same behavior. React does the same when `action` is a function, so your form works consistently before and after JavaScript loads.

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.

this paragraph reads a little strange, and the behavior was explained better above!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

is 4f39d4b better?


</Sandpack>

Because you call the action manually from `onSubmit`, [`useFormStatus`](/reference/react-dom/hooks/useFormStatus) won't report its pending state. Read `isPending` from the same [`useTransition`](/reference/react/useTransition) call instead.

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.

Hm, i thought useFormStatus worked regardless, also with onSubmit?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

yep, I got just using onSubmit without action confused

When a user taps a specific button, the form is submitted, and a corresponding action, defined by that button's attributes and action, is executed. For instance, a form might submit an article for review by default but have a separate button with `formAction` set to save the article as a draft.
When a button without `formAction` submits the form, React calls the form's `action`. When a button with `formAction` submits the form, React calls that button's action instead. For example, the form below publishes an article by default, but its **Save draft** button stores the current content without publishing it.

In this example the draft is held in state, so the saved content stays in the textarea after you submit it. In a real app you would persist the draft on the server. Pass a [Server Function](/reference/rsc/server-functions) (a function marked with [`'use server'`](/reference/rsc/use-server)) to `formAction` to save the draft from the server, optionally combined with [`useActionState`](/reference/react/useActionState) to track its pending state and result.

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.

(a function marked with 'use server')

is this a common pattern in the docs?

@MaxwellCohen MaxwellCohen Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Most of the examples are called out in the code update it in code, so moving to code and using useActionState
947c926

@aurorascharff aurorascharff Jul 6, 2026

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.

To be clear, sorry if this was too biref, i was wondering about the usage of the () inline linking of in that way!!

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.

But i think its better the way you did it regardless

function EditForm() {
// The action returns { submitted: formData, error } on failure
const [state, formAction] = useActionState(submitForm, {});
const values = state.submitted ?? new FormData();

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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good point, I forgot about optional chaining (one of my favorite JS features when working on making the examples)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Suggestion]: improve <Form> documentation to explain how to keep form state after submission

2 participants