← Back

useFormStatus in SubmitButton

SubmitButton component pattern, why it must be a child of the form.

PublishedMarch 5, 2026143 words
Edit

useFormStatus

useFormStatus provides the pending state of the nearest parent form. It's the simplest way to show loading indicators during form submissions.

Example: SubmitButton

From components/design/SubmitButton.tsx:

'use client'; import { useFormStatus } from 'react-dom'; export function SubmitButton({ children }) { const { pending } = useFormStatus(); return ( <button type="submit" disabled={pending}> {pending ? <Spinner /> : children} </button> ); }
'use client'; import { useFormStatus } from 'react-dom'; export function SubmitButton({ children }) { const { pending } = useFormStatus(); return

The Child Component Constraint

The hook only works in components that are children of the form:

// ❌ Always returns pending: false function Form() { const { pending } = useFormStatus(); return <form>...</form>; } // ✅ Works - SubmitButton is a child of the form

React needs to track which form triggered the submission. By requiring the hook inside a form's children, React reliably determines the pending state for that specific form.

(
<
button
type
=
"
submit
"
disabled
=
{
pending
}
>
{
pending
?
<
Spinner
/>
:
children
}
</
button
>
)
;
}
<
form
action
=
{
formAction
}
>
<
SubmitButton
>
Save
</
SubmitButton
>
</
form
>
// ❌ Always returns pending: false function Form() { const { pending } = useFormStatus(); return <form>...</form>; } // ✅ Works - SubmitButton is a child of the form <form action={formAction}> <SubmitButton>Save</SubmitButton> </form>