Form with useActionState
Medium · Server Actions
React 19's useActionState wraps an action (like a Server Action) and keeps its latest result as state:
``tsx
const [state, dispatch, isPending] = useActionState(saveProfile, initialState);
``
Calling dispatch(payload) runs saveProfile(previousState, payload). Whatever the action returns becomes the new state, and isPending is true while it runs. The server can send back validation errors or a success message, and the form just renders state.
The most common way is <form action={dispatch}>: React then collects the fields into a FormData, runs the action in a transition, and resets the form afterwards. Here the inputs are **controlled** (kept in useState), so you call the action yourself. That is also what you do when the data does not come straight from a form, e.g. with a form library. In that case dispatch must be called **inside a transition**, otherwise isPending does not update:
``tsx
startTransition(() => dispatch({ name, email }));
``
The fake server action saveProfile and the input state are already written. Finish ProfileForm:
- Use useActionState(saveProfile, initialState) and dispatch { name, email } from onSubmit (inside startTransition, after event.preventDefault()).
- Show each field error from state.errors in a <p className="error">.
- While pending, the submit button is disabled and reads Saving…, otherwise Save.
- Show state.message in a <p className="success"> when it is not empty.
Next: Optimistic Like Button