Lesson 16 / 25

Form UX: Pending States and Errors

Feedback while the server works.

useActionState and useFormStatus

Users need feedback while an action runs and when it fails. React's useActionState gives you the action's latest result (for example validation errors) and a pending flag; useFormStatus exposes pending state to components inside a form, such as a submit button. Disable the button while pending, show field errors returned by the action, and consider optimistic updates (useOptimistic) for actions that usually succeed.

A submit button with pending state (sketch)

Client Component used inside a form; not run here.

"use client";
import { useFormStatus } from "react-dom";

export function SubmitButton() {
  const { pending } = useFormStatus();
  return <button type="submit" disabled={pending}>{pending ? "Saving..." : "Save"}</button>;
}

Return errors, do not throw them

For expected problems (validation, permissions) return an error object the UI can display; reserve thrown errors for unexpected failures.

Quick check: Which hook exposes a form's pending state to a child button?

  • useRef
  • useEffect
  • useFormStatus
  • useId
Answer

useFormStatus — Pending state comes from the parent form.