--- name: using-action-state description: Teaches useActionState hook for managing form state with Server Actions in React 19. Use when implementing forms, handling form submissions, tracking pending states, or working with Server Functions. allowed-tools: Read, Write, Edit, Glob, Grep version: 1.0.0 --- # useActionState Patterns for Forms Teaches React 19's `useActionState` hook for form state management with Server Actions. When: mentioning `useActionState`, form state/handling, Server Actions/Functions; tracking pending/submission status; implementing progressive enhancement; server-side form validation. `useActionState` manages form state based on action results: tracks pending state (automatic `isPending`), manages form state (returns action results), integrates Server Actions (`'use server'`), enables progressive enhancement (optional no-JS permalink). Replaces manual form submission state management. ## Standard Form with useActionState **Server Action:** ```javascript 'use server'; export async function submitForm(previousState, formData) { const email = formData.get('email'); if (!email || !email.includes('@')) { return { error: 'Invalid email address' }; } await saveToDatabase({ email }); return { success: true }; } ``` ```` **Component:** ```javascript 'use client'; import { useActionState } from 'react'; import { submitForm } from './actions'; function ContactForm() { const [state, formAction, isPending] = useActionState(submitForm, null); return (
{state?.error &&

{state.error}

} {state?.success &&

Submitted!

}
); } ```
## Decision Points **Progressive Enhancement:** Add permalink as third argument: `useActionState(submitForm, null, '/api/submit')`. Form submits to URL before JS loads; server handles both cases. **Validation:** Server Action receives previousState, returns error object for failures, success object when valid; component renders errors from state. **Multi-Step Forms:** Track step in state; Server Action advances step or returns errors; component renders current step. ## References - **Server Actions**: `../../forms/skills/server-actions/SKILL.md` - **Form Validation**: `../../forms/skills/form-validation/SKILL.md` - **Progressive Enhancement**: `../../../research/react-19-comprehensive.md` (lines 715-722) **Cross-Plugin References:** - If customizing validation error messages, use the customizing-errors skill for error formatting with safeParse and field error flattening Load as needed for specific patterns. ## Example 1: Validation with Zod ```javascript 'use server'; import { z } from 'zod'; const schema = z.object({ email: z.string().email(), message: z.string().min(10).max(1000), }); export async function contactAction(previousState, formData) { const data = { email: formData.get('email'), message: formData.get('message'), }; const result = schema.safeParse(data); if (!result.success) { return { errors: result.error.flatten().fieldErrors }; } try { await db.contacts.create({ data: result.data }); return { success: true }; } catch (error) { return { error: 'Failed to submit contact form' }; } } ``` ```javascript 'use client'; import { useActionState } from 'react'; import { contactAction } from './actions'; export default function ContactForm() { const [state, formAction, isPending] = useActionState(contactAction, null); if (state?.success) { return

Thank you for contacting us!

; } return (
{state?.errors?.email && {state.errors.email}}