Skip to content

Update form documentation for forms default reset behavior#8512

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

Update form documentation for forms default reset behavior#8512
MaxwellCohen wants to merge 17 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.
Comment thread src/content/reference/react-dom/components/form.md Outdated
Comment thread src/content/reference/react-dom/components/form.md Outdated
Comment thread src/content/reference/react-dom/components/form.md Outdated
Comment thread src/content/reference/react-dom/components/form.md Outdated
Comment thread src/content/reference/react-dom/components/form.md Outdated
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.

Why do we need a seperate variable for values? Is this pattern better than returning the values from the useActionState function?

https://aurorascharff.no/posts/handling-form-validation-errors-and-resets-with-useactionstate/
https://www.robinwieruch.de/react-server-action-reset-form/

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)

export default function Search() {
function handleSubmit(e) {
// Prevent the browser from reloading the page
e.preventDefault();

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.

Why was this e.preventDefault() removed? 🤔

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.

I removed e.preventDefault() to show that, by default, forms reset their values. My goal is to progressively disclose the behavior of forms. React extends HTML form behavior with the onSubmit and action props, not replaces it. I think this is the brilliance of React 19 form APIs.

React is at its best when it takes something that was hard, such as updating content on the page or building reusable components, and makes it easy (sometimes too easy with useEffect 😉 ). I see the form APIs as the next step of this.

If it is unclear, or better to have it, I am open to suggestions.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

hmm yeah i wasn't sure why this was removed either. I don't really have strong feelings either way tho


When you pass a function to `action` or `formAction`, React resets the form's [uncontrolled fields](/reference/react-dom/components/input#reading-the-input-values-when-submitting-a-form) after the action succeeds. This reset only affects uncontrolled fields—[inputs controlled with state](/reference/react-dom/components/input#controlling-an-input-with-a-state-variable) are never cleared.

To preserve the values of uncontrolled fields after submission, add an `onSubmit` handler that calls `e.preventDefault()` and runs the action inside a [Transition](/reference/react/useTransition). Keep the `action` prop on the form so it continues to work before JavaScript loads.

@hernan-yadiel hernan-yadiel Jul 6, 2026

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.

I just tried this and it calls both: the submitForm action and the handleSubmit function.

If we want the form to progressively enhance and at the same time preserving values after submission, I believe the right answer is useActionState.

"use client";

import { useActionState } from "react";
import { someServerFunction } from "./some-server-function";

export default function EditForm() {
  const [state, dispatchAction, isPending] = useActionState(someServerFunction, {
    title: "My draft",
  });

  return (
    <form action={dispatchAction}>
      <input name="title" defaultValue={state.title} />
      <button type="submit" disabled={isPending}>
        {isPending ? "Saving..." : "Save"}
      </button>
    </form>
  );
}

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.

Thank you very much for looking into this.

handleSubmit includes submitForm so both functions will be called in onSubmit.
This comment made me think we should show multiple examples of resetting a form rather than just one. So I added a Recipe with 3 examples of state-keeping. 2cb1370

Comment thread src/content/reference/react-dom/components/form.md Outdated
Comment on lines +186 to +187
export default function EditForm() {
const [isPending, setIsPending] = useState(false);

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.

I think this is a pattern we should stop recommending now that we have better primitives, so I would just drop this example and leave the other two which are "Async React compliant". What do you think?

@MaxwellCohen MaxwellCohen Jul 7, 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.

Very good point. I removed this example in a3cd240

@MaxwellCohen MaxwellCohen changed the title Enhance form documentation for form default reset behavior Update form documentation for forms default reset behavior Jul 8, 2026
### Handling form submission with an event handler {/*handle-form-submission-with-an-event-handler*/}

Pass a function to the `onSubmit` event handler to run code when the form is submitted. By default, the browser sends the form data to the current URL and refreshes the page, so call [`e.preventDefault()`](https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault) to override that behavior.
Pass a function to the `onSubmit` event handler to run code when the form is submitted. By default, the browser sends the form data to the current URL and refreshes the page. Call [`e.preventDefault()`](https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault) in your handler to override that behavior.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

maybe change to in your event handler instead of just handler thought its probably pretty obvious

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.

upated in cfb4422


### Preserving form values after submission {/*preserve-form-values-after-submission*/}

By default, the browser clears a form's input state after submission. Forms with a URL `action` follow this behavior, and React mirrors it when `action` is a function-ensuring your form behaves consistently both before and after JavaScript loads.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This should probably be 2 seperate words function-ensuring?

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.

cleaned up in cfb4422


#### `onSubmit` and `action` {/*with-onsubmit-and-usetransition*/}

Adding an `onSubmit` handler that calls `e.preventDefault()` will run instead of the `action` prop.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

so if you don't preventDefault it will run the action prop function? onSubmit doesn't always override?

@MaxwellCohen MaxwellCohen Jul 10, 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.

That is correct; you can use onSubmit as a logging check, so you would not want to override the default browser behavior. I added a comment to better explain the behavior.

cfb4422


The `onSubmit` approach above keeps every uncontrolled field. When you need finer control, two other patterns are available:

* **Reset from your own Action API.** If you build an Action-based API and still want the form to reset after the Action runs, call the `requestFormReset` API from `react-dom` with the form element inside the Transition.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

did not know this api existed

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.

make this issue to get it documented #8529

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

4 participants