useFormStatus
Read the pending state of the parent form from inside a child component.
Syntax
const { 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
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.
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.
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.
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