Pending States (useFormStatus)

Context-aware pending states for nested form components.

Next.js5 min readConcept 34 of 65

Implicit Form Context

useFormStatus is a React Hook that gives you access to the status of a form submission.

Under the hood, native <form> elements in modern React act like Context Providers. Any child component inside the form can use this hook to instantly know if the form is currently submitting.

Reusable Submit Buttons

Historically, to disable a submit button while loading, you had to manage an isSubmitting state at the top of your component and pass it down as a prop: <SubmitButton disabled={isSubmitting} />.

With useFormStatus, the button manages itself. You can build a generic <SubmitButton> that automatically disables itself and shows a spinner whenever the parent form is pending.

The Pending Flag

Inside your child component, call the hook: const { pending } = useFormStatus();.

Use that boolean to conditionally style the button or disable it to prevent double-submissions: <button disabled={pending}>.

The Component Boundary

Submit the form below. Notice how the nested <SubmitButton> automatically detects the pending state and shows a spinner. The visual highlights the strict component boundary required to make the hook work.

Component Tree

page.tsx (Parent)

Newsletter Signup

pending = true
SubmitButton.tsx (Child)

Code Wiring

page.tsxProvides Context
export default function Page() {
return (
// Native form creates the context provider
<form action={myAction}>
<input name="email" />
// Must be a separate component!
<SubmitButton />
</form>
);
}
SubmitButton.tsx Consumes Context
const { pending } = useFormStatus();

export function SubmitButton() {
// Hook reads from nearest parent <form>
return (
<button
type="submit"
disabled={false}
>
{pending ? 'Pending...' : 'Subscribe'}
</button>
);
}

Check yourself

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

  1. 1Why will `useFormStatus` fail to update if called in the same component that renders the `<form>`?
  2. 2Will `useFormStatus` track a Server Action triggered via an `onClick` handler on a button outside of a form?

Remember this

  • useFormStatus reads pending state implicitly from a parent <form>.
  • It is primarily used for creating reusable <SubmitButton> components.
  • You MUST call it from a child component inside the form.
  • Calling it in the same component that renders the form will result in pending always being false.
  • It only works with form submissions, not manual onClick RPC mutations.

Done with this concept?

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