Handling Forms via Form ActionsEntry 6 of 10
useFormStatus: Pending State in Child Components
useFormStatus() (from react-dom) returns the submission status of the parent <form>: { pending, data, method, action }.
Notes
- The component calling it must be rendered inside the
<form>. It reads the nearest ancestor form, not a form rendered in the same component. - Its main use: a reusable
<Submit>button that disables itself, with no props passed down. datais theFormDatabeing submitted (nullwhen idle), useful for showing what's being sent.- It works with any function
action, with or withoutuseActionState.
| Aspect | useActionState | useFormStatus |
|---|---|---|
| Package | react | react-dom |
| Called in | The component that renders the form | A component inside the form |
| Gives | state, formAction, isPending | pending, data, method, action |
| Use for | Results and errors | Reusable buttons and spinners |
What / Why / When
- What
Form status available to any descendant.
- Why
No prop drilling of
isPendinginto buttons.- When
Shared submit buttons or loading indicators used across forms.
- Use case
A
<Submit>button used in the opinion form.
Code compare
// Submit.tsximport { useFormStatus } from "react-dom";export default function Submit() { const { pending } = useFormStatus(); return ( <p className="actions"> <button type="submit" disabled={pending}> {pending ? "Submitting..." : "Submit"} </button> </p> );}There's no context-based form status. The usual pattern passes the pending signal down as an input:
// submit-button.component.ts@Component({ selector: "app-submit-button", template: ` <p class="actions"> <button type="submit" [disabled]="pending()"> {{ pending() ? "Submitting..." : "Submit" }} </button> </p> `,})export class SubmitButtonComponent { pending = input(false);}To avoid passing it through several levels, provide a small state service on the form component (providers: [FormStatusService]) and inject() it in the button. Children get the same instance, which mimics useFormStatus.
Differences and gotchas
- Calling
useFormStatus()in the same component that renders the<form>always returnspending: false. Move it into a child. - Import from
react-dom, notreact.
Quick reference
| React 19 | Angular |
|---|---|
useFormStatus() in a child | pending input, or a component-level service |
pending | isPending() signal |
data | form.getRawValue() |