diff --git a/src/content/reference/react-dom/components/form.md b/src/content/reference/react-dom/components/form.md index 10e9c67940e..440ca94608a 100644 --- a/src/content/reference/react-dom/components/form.md +++ b/src/content/reference/react-dom/components/form.md @@ -38,31 +38,33 @@ To create interactive controls for submitting information, render the [built-in `
` supports all [common element props.](/reference/react-dom/components/common#common-props) -[`action`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form#action): a URL or function. When a URL is passed to `action` the form will behave like the HTML form component. When a function is passed to `action` the function will handle the form submission in a Transition following [the Action prop pattern](/reference/react/useTransition#exposing-action-props-from-components). The function passed to `action` may be async and will be called with a single argument containing the [form data](https://developer.mozilla.org/en-US/docs/Web/API/FormData) of the submitted form. The `action` prop can be overridden by a `formAction` attribute on a ` +
+ ); +} +``` + +```js src/api.js hidden +export async function submitForm(previousState, formData) { + await new Promise((res) => setTimeout(res, 1000)); + return { + title: formData.get("title"), + }; +} +``` + + + + + +#### Keep every field with `onSubmit` {/*with-onsubmit-and-action*/} + +Call `e.preventDefault()` in an `onSubmit` handler and run the Action yourself with [`startTransition`](/reference/react/useTransition). React does not reset the form because the `action` prop never runs. + + + +```js src/App.js active +import { useTransition } from "react"; +import { submitForm } from "./api.js"; + +export default function EditForm() { + const [isPending, startTransition] = useTransition(); + + function handleSubmit(e) { + // Stop React from resetting the form after the Action succeeds + e.preventDefault(); + const formData = new FormData(e.target); + startTransition(async () => { + await submitForm(formData); + }); + } + + return ( +
+ + +
+ ); +} +``` + +```js src/api.js hidden +export async function submitForm(formData) { + await new Promise((res) => setTimeout(res, 1000)); +} +``` + +
+ + + + + + + +#### Resetting only some fields, or resetting on the server {/*deep-dive-resetting-only-some-fields*/} + +The `onSubmit` approach above keeps every uncontrolled field. For finer control, you can: + +* **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 [`requestFormReset`](/blog/2024/12/05/react-19#form-actions) from `react-dom` with the form element inside the Transition. + +* **Reset to server-provided values on validation failure.** The [`useActionState`](#with-useactionstate) example above preserves values after a successful submission. When an Action validates input on the server, you can return the submitted `FormData` and pass it to each field's `defaultValue`. React restores those values instead of clearing them, and the form keeps working before JavaScript loads: + +```js +import { useActionState } from "react"; +import { submitForm } from "./actions.js"; + +function EditForm() { + // The Action returns { submitted: formData, error } on failure + const [state, formAction] = useActionState(submitForm, { + error: "", + }); + return ( +
+ + {state.error &&

{state.error}

} + +
+ ); +} +``` + +Return the original `FormData` object rather than a new one so React can restore the values even before JavaScript has loaded. + +
+ +--- ### Handling multiple submission types {/*handling-multiple-submission-types*/} -Forms can be designed to handle multiple submission actions based on the button pressed by the user. Each button inside a form can be associated with a distinct action or behavior by setting the `formAction` prop. +A form can have more than one submit button, each running a different Action. Set the `formAction` prop on a `