In short
Login, sign-up, search, checkout: forms are everywhere. React 19 makes them simpler by letting a form call your function directly with all its data.
Handling user input in React — reading values, tracking state per field, validating and submitting — often the most state-heavy part of a UI.

Think of it like this
A bank deposit slip
You fill in your name, account number and amount, then hand the whole slip to the cashier at once. You don't shout each field separately. A form action works the same way: the browser bundles every field into a FormData slip and hands it to your function.
Watch it happen
A form action, start to finish
type + Subscribe
1/6You type an email and press Subscribe.
The big ideas
What you need to know
name is what matters
Every input needs a name attribute. That's the key you read it by, like formData.get("email").
onSubmit or action
Classic way: onSubmit with e.preventDefault(). React 19 way: pass a function to the form's action prop.
Show the pending state
useActionState gives you the result and an isPending flag, so you can disable the button while it saves.
Validate twice
Use required, type="email" and minLength for quick checks in the browser, and always validate again on the server.
See it in code
Walk through the code
1import { useActionState } from "react";2async function subscribe(_prev: string, formData: FormData) {3 const email = formData.get("email");4 await new Promise((r) => setTimeout(r, 1000)); // pretend API call5 return "Subscribed " + email;6}7export default function Newsletter() {8 const [message, formAction, isPending] = useActionState(subscribe, "");9 return (10 <form action={formAction}>11 <input name="email" type="email" required />12 <button disabled={isPending}>{isPending ? "Saving..." : "Subscribe"}</button>13 <p>{message}</p>14 </form>15 );16}1/4The action gets the previous state and FormData, and reads the field by its name.
React calls subscribe with the form's data and puts its return value in message. Once the action finishes, React resets the form's uncontrolled fields for you.
Save yourself the pain
Common mistakes
Oops
Using onSubmit and forgetting e.preventDefault().
Do this instead
Without it the browser reloads the page. Call it first, or use the action prop, which handles this for you.
Oops
Inputs with no name attribute.
Do this instead
FormData only collects fields that have a name. No name, no value.
Your mission
Sign-up form with a spinner
Quick check
A form has <input type="email" /> with no name. What does formData.get("email") return?
Go deeper
- 1Build a form with multiple fields tracked in a single state object.
- 2Practice basic validation and displaying inline error messages.
- 3Try a form library (React Hook Form) once you understand the manual approach.
More topics at this stop
Stuck on this topic? Ask an Insider
Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.