Chapter 5 · Practice 2 of 5
Track results and errors with useActionState
Why it matters
useActionState(action, initialState) returns three things:
- the current state,
- a wrapped action to pass to the form,
- an
isPendingflag.
Your action receives the previous state and the form data, and whatever it returns becomes the new state. That makes it the clean place to return validation errors or a success message.
Example
async function signUp(prev: State, formData: FormData): Promise<State> {
const email = String(formData.get('email'));
if (!email.includes('@')) return { error: 'Enter a valid email' };
await createAccount(email);
return { error: null };
}
function SignUpForm() {
const [state, formAction, isPending] = useActionState(signUp, { error: null });
return (
<form action={formAction}>
<input name="email" />
<button disabled={isPending}>Sign up</button>
{state.error && <p role="alert">{state.error}</p>}
</form>
);
}