useFormStatus

Read the pending state of the parent form from inside a child component.

Syntaxconst { pending } = useFormStatus();

useFormStatus lets a component read the submission status of the nearest parent form without prop drilling. It is ideal for reusable submit buttons that disable themselves while the form is pending.

What it returns

  • pending — true while the form's action is running.
  • data, method, action — details about the in-flight submission.

The component using it must be rendered inside the <form>, not the component that renders the form.

Example

Example · javascript
import { useFormStatus } from 'react-dom';

function SubmitButton() {
  const { pending } = useFormStatus();
  return (
    <button type="submit" disabled={pending}>
      {pending ? 'Submitting...' : 'Submit'}
    </button>
  );
}

function ContactForm({ action }) {
  return (
    <form action={action}>
      <input name="email" />
      <SubmitButton />
    </form>
  );
}

When to use it

  • A reusable SubmitButton component uses useFormStatus to disable itself and show a spinner whenever any form it lives inside is pending, without receiving props.
  • A design system ships a FormField component that reads useFormStatus to grey out all fields while a form submission is in flight, centralising the UX in one component.
  • A checkout button calls useFormStatus inside a deeply nested component so it reflects the parent form's payment-processing state without threading isPending through multiple layers.

More examples

Self-disabling submit button

Reads the parent form's pending status with useFormStatus to disable itself and update its label automatically.

Example · jsx
import { useFormStatus } from 'react-dom';

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

// Use inside any form with an action
// <form action={myAction}><SubmitButton label="Save" /></form>

Pending overlay on form

Renders a loading overlay during submission using useFormStatus, keeping the overlay logic isolated from the form.

Example · jsx
import { useFormStatus } from 'react-dom';

function FormOverlay() {
  const { pending } = useFormStatus();
  if (!pending) return null;
  return (
    <div className="overlay" aria-live="polite">
      <span className="spinner" /> Processing...
    </div>
  );
}

function PaymentForm({ action }) {
  return (
    <form action={action}>
      <FormOverlay />
      <input name="card" />
      <button type="submit">Pay</button>
    </form>
  );
}

Disable all inputs while pending

Wraps inputs in a fieldset that reads useFormStatus to disable all controls at once during submission.

Example · jsx
import { useFormStatus } from 'react-dom';

function DisabledDuringSubmit({ children }) {
  const { pending } = useFormStatus();
  return (
    <fieldset disabled={pending} style={{ border: 'none', padding: 0 }}>
      {children}
    </fieldset>
  );
}

function SettingsForm({ action }) {
  return (
    <form action={action}>
      <DisabledDuringSubmit>
        <input name="username" />
        <input name="bio" />
      </DisabledDuringSubmit>
      <button type="submit">Save</button>
    </form>
  );
}

Discussion

  • Be the first to comment on this lesson.