useActionState
React chapter 21 · React 19 · form actions · source: react.dev/reference/react/useActionState
The problem
A form needs "is it saving?", "did it fail?" and "what was saved?". Written by hand that is several useStates plus an onSubmit, and a button in a child component cannot see "saving" at all.
The pattern that fixes it
useActionState(action, initial) returns [state, formAction, isPending]. Give formAction to <form action>, and a child can read pending with useFormStatus(), no props needed.
In plain words
Submitting a form is a little story: you click, you wait, you get a result or an error. useActionState lets you write that story as one function and React keeps track of the waiting and the result for you.
Ordering at a counter. Writing it by hand, you keep a notepad ("order placed? paid? error?"). With an action, the cashier owns the notepad and just tells you "still working" or "here is your result".
Terms
- action
- A function you hand to a form. React calls it with the form data when the form is submitted, and it may be async.
- pending
- True while the action is still running (waiting for the server).
- useFormStatus
- A hook a component inside a form uses to read that form's pending status without receiving a prop.
- reducer-style state
- The action gets the previous state and returns the next state, like a useReducer that can wait.
Going deeper
How does it work?
On submit React calls your action as action(previousState, formData). While the returned promise is unsettled, isPending is true. When it settles, whatever it returned becomes the new state. If the user submits again while one is running, React queues the calls and runs them in order, each one receiving the state produced by the one before.
Pitfalls
useFormStatus only sees a form it is inside of, so call it in a child component, never in the component that renders the <form>. It also reports nothing for a form that uses onSubmit instead of action. After a successful action React resets uncontrolled inputs, so return the typed text in your state and use it as defaultValue if you want it kept. A plain submit button does not disable itself: queued double-submits are safe but usually not what you want, so disable on pending.
When not to use it
For one-off clicks that are not forms (a "Like" button), a plain async handler or useTransition is simpler. For live validation on every keystroke keep a controlled input. For server data that many components share, a data library (TanStack Query, framework loaders) gives caching and retries that an action does not. The React Compiler does not replace this hook; it solves a different problem (re-renders).
Keep learning
- Previous: useOptimistic
- Next: Activity
- Related: memo
- Related: useMemo
- Related: useCallback
- Related: Custom hooks
- Related: useEffectEvent
- Related: useTransition
More courses
- Jobs, linked to lessons — Browse jobs where every requirement links to the chapter that teaches it. See how ready you are, how long the gap takes to close, and which listings look stale.
- Match a job post to courses — Paste a job post. Each skill is matched to a track here and put in learning order, foundations first.
- Database in depth — How a query becomes work. Indexes, isolation, locks, and the plans that explain why a page is slow — not an ORM tour.
- System Design — Eight interview case studies, from a flash sale and Tatkal to a live final and a chat model, plus JWT in separate chapters.
- Microservices — Microservice patterns one diagram at a time: how to split a monolith, how services talk, and how data stays consistent without distributed transactions.
- Kafka — A beginner-to-senior path through event logs, reliable delivery, production operations, and disaster recovery.
- Frontend system design — How a UI is sliced when it is a product, not a page: ownership of state, cache, routes, and what happens when the network lies.
- CSS in depth — See the box, then the page. Visual chapters from the box model through Flexbox surprises, Grid, selectors, and units, then backgrounds, shapes, and visual effects, each with a playground.
- Accessibility — HTML labs first, then a full pass of WAI-ARIA 1.3: naming, every state, widget and structure roles, live regions, ariaNotify, and relationships.
- Docker — What an image is, why layers cache, and how containers find each other on a network.
- Redis — Fifteen Redis patterns, one picture each: cache, session, lock, counter, rate limiter, queue, and when Redis is the wrong tool.