Form Actions

In React 19 7,897 the action prop of a <form> accepts a function instead of a URL. React intercepts the submit, builds a FormData from the fields, calls your function with it, and — if the function returns without throwing — resets the form. The call runs inside a transition, so the UI stays responsive and the pending state is visible to useFormStatus. <button> and <input type="submit"> take a matching formAction prop, which lets one form route to different handlers.

A form action reading FormDataJavaScript
function Subscribe() {
  const [saved, setSaved] = useState(null);
  async function subscribe(formData) {         // React hands you the FormData
    await fetch('https://api.example.com/subscribe', { method: 'POST', body: formData });
    setSaved(formData.get('email'));           // the fields reset themselves
  }
  return (
    <form action={subscribe}>
      <input name="email" type="email" required />
      <button>Subscribe</button>
      {saved && <p>Subscribed {saved}.</p>}
    </form>);
}

Note what is absent: no onSubmit, no event.preventDefault(), no state variable per field. Every input needs a name, because name is the FormData key — and FormData goes to fetch directly, which is how file uploads come along for free. The reset happens only on success, so a handler that throws leaves the user's typing in place, and noValidate on the <form> turns off the browser's own pass when you want to own the messages.