Form State (useActionState)

Connecting Server Action results directly to UI state.

Next.js7 min readConcept 33 of 65

The Server-to-Client Bridge

useActionState is a React Hook that allows you to update a component's state based on the result of a Server Action.

When a user submits a form, the action runs on the server and returns a value (like an error message or a success object). This hook automatically pipes that return value straight into your UI.

Handling Validation Errors

Without this hook, handling server-side validation is tedious. You would have to manually intercept the form submission, track a pending state, and manually update a state variable with the server's response.

useActionState handles all of this declaratively while preserving Progressive Enhancement.

Wiring the Hook

You initialize it with const [state, formAction, isPending] = useActionState(myAction, initialState).

Crucially, the Server Action signature must change. It now receives the previousState as its first argument, and the FormData as its second argument: async function myAction(prevState, formData).

The Validation Loop

Try registering a username. If you use a taken username like 'admin', the Server Action will reject it and return an error state. Watch how useActionState instantly pipes that server error directly into the input field's UI.

Client Component

Register

Hint: Try registering the username admin.

Hook Wiring

const [state, action, isPending] = useActionState(
  registerUser,
  { message: "" }
);

Next.js Server

actions.ts
'use server';

export async function registerUser(
  prevState: any, // Required first arg
  formData: FormData
) {
const username = formData.get('user');

if (username === 'admin') {
  return { message: 'Username taken.' };
}

// Save to DB...
  return { message: 'Success!' };
}

Check yourself

Pick an answer to lock it in, then read why. Getting one wrong is part of how it sticks.

  1. 1When using `useActionState`, what must the signature of your Server Action look like?
  2. 2Does `useActionState` preserve Progressive Enhancement?

Remember this

  • useActionState updates UI state based on the return value of a Server Action.
  • It is primarily used for returning server-side validation errors to the client.
  • The hook returns [state, formAction, isPending].
  • The Server Action MUST be updated to accept (prevState, formData).
  • It preserves Progressive Enhancement, falling back to a native POST if JS is disabled.

Done with this concept?

Mark it complete to track your progress. No login needed.