Optimistic UI — useActionState + useFormStatus + useOptimistic
Optimistic UI — useActionState + useFormStatus + useOptimistic
💡 Why learn this? — The 'brief pause after clicking' disappears
3 hooks — division of responsibility
1. The role of each hook
2. useActionState (React 19 — replaces the old useFormState)
The Action signature changes to (prevState, formData) => newState.
3. useFormStatus — child reads parent form state
Placed anywhere inside the parent <form>, it automatically receives that form's state. No props drilling.
4. useOptimistic — immediate UI update + auto-rollback
5. All three together — a complete form
💡 💡 Optimistic UI in practice — 5 tips
1. Call useOptimistic inside startTransition
Calling it without a Transition makes it a synchronous update, which weakens the effect.
2. Add a marker like pending: true to optimistic items
Give the user a visual signal that 'the server hasn't confirmed this yet' (opacity 0.5, 'Sending' label).
3. No extra code needed for failure — React auto-rolls back
If the Server Action throws, the optimistic state is discarded and the original value is restored. Just add an error toast in the catch.
4. Auto-sync when the real value arrives after revalidatePath
Call revalidatePath at the end of the Server Action → page data is re-fetched → the initial value of useOptimistic is updated → optimistic state is automatically discarded.
5. Use with useActionState — manage the entire form state