useActionState & useOptimistic: Form Transitions & Instant UI Updates
- Last updated
- Prerequisites:
- React 19 Actions
- HTML Forms and FormData
- react
- useActionState
- useOptimistic
- forms
- actions
- react-19
Read at your depth
The practical view
`useActionState` (formerly `useFormState`) manages form action lifecycles: `const [state, formAction, isPending] = useActionState(actionFn, initialState)`. `useOptimistic` allows you to render optimistic state while an action is in flight: `const [optimisticList, addOptimistic] = useOptimistic(list, (current, newItem) => [...current, newItem])`. When the action completes, React replaces the optimistic state with the true server result automatically.
The same idea in other frameworks
`useActionState` + `useOptimistic` for declarative form actions and rollbacks.Manual RxJS BehaviorSubject tap/catchError rollback patterns.Pinia optimistic store mutations with catch error rollback.SvelteKit `enhance()` action with custom optimistic UI callbacks.Legacy vs modern
Manual Try-Catch Rollback vs useActionState + useOptimistic
Manual optimistic state requires messy error flags and duplicate rollback state; React 19 handles optimistic rollbacks declaratively.
setList(prev => [...prev, item]); try { await save(); } catch { setList(backup); } // ❌ Fragileconst [optimisticTodos, setOptimistic] = useOptimistic(todos, (state, newTodo) => [...state, newTodo]); // ✅ NEWInterview gotchas
Context
Interviewers test your knowledge of automatic error recovery in React 19 actions.
The mechanical answer
If the action throws an error or rejects, the transition fails. React automatically discards the optimistic overlay during the next render cycle, snapping the UI back to the current committed state without requiring manual rollback code.
Trap
Optimistic updates only stay alive while the enclosing transition is pending. As soon as the transition completes (successfully or with an error), the optimistic value is discarded.
Context
Tests lifecycle scope requirements of the hook.
The mechanical answer
Calling the update function returned by `useOptimistic` outside a transition (such as inside a raw `onClick` handler without `startTransition` or `<form action>`) will trigger a React warning, and the optimistic update will be ignored or immediately reverted on the next render.
Trap
Always ensure optimistic mutations occur inside a `startTransition` callback or an async `<form action>`.