React 19 overloaded the HTML form's action attribute. Pass a string and the browser handles submission as it has since 1993. Pass a function and React owns the lifecycle.
The two modes
<form action="/save" method="POST">— full-page browser submit. Works without JS. The mode the web has always had.<form action={saveFn}>— React intercepts submission, callssaveFn(formData), manages the pending state, prevents the default browser submit. JS required. The mode React 19 added.
The function mode is what unlocks the Actions story. The hooks in the next five lessons (useActionState, useFormStatus, useOptimistic) all assume the form is in function-action mode.
FormData as the input
Your action function receives a FormData object — the standard browser type for serialized form fields. Read fields with formData.get('name'); check files with formData.get('avatar') instanceof File. No JSON parsing, no manual field collection.
Reset on submit
After an Action runs successfully, React clears the form's uncontrolled inputs (resets the form). If you want to keep values (controlled inputs, multi-step forms), manage the values yourself with useState.
What happens to native form behaviors
HTML validations still fire first (required, type=email, minlength). If the user's input fails native validation, the Action doesn't run. Inside the Action you get already-validated input — though you should still validate server-side for security (lesson 6 on Zod).
onSubmit + e.preventDefault + collect fields + fetch + setState dance.