DevAcademy
LearnReactuseFormStatus
AdvancedReact

useFormStatus

Learn how to read the pending status of the nearest parent form from a child component, without prop drilling.

Reading Time

14 min

Lesson

Lesson 30 of 42

The Problem: A Submit Button Needs to Know the Form’s Status

A reusable submit button component often needs to show a pending state (disabling itself, showing a spinner) while its parent form is submitting — but that pending state usually lives in the parent, not the button itself.

What useFormStatus Does

useFormStatus() (imported from react-dom) reads the status of the nearest parent <form> from within a child component — with no props needed at all. It only works for a component rendered inside a form, reading that form’s live submission status.

A Reusable Submit Button

import { useFormStatus } from "react-dom";

function SubmitButton() {
  const { pending } = useFormStatus();

  return (
    <button type="submit" disabled={pending}>
      {pending ? "Saving..." : "Save"}
    </button>
  );
}

function ProfileForm({ updateProfile }) {
  return (
    <form action={updateProfile}>
      <input type="text" name="name" />
      <SubmitButton /> {/* knows the form's pending status automatically */}
    </form>
  );
}

useFormStatus Return Value

PropertyMeaning
pendingtrue while the parent form’s action is in flight
dataThe FormData currently being submitted
methodThe HTTP method used for the submission ("get" or "post")
actionA reference to the action function the parent form is using

Must Be Called from a Component Inside the form

useFormStatus only returns meaningful status when called from a component rendered as a descendant of a <form> — calling it in the same component that renders the <form> itself always returns the default, non-pending status, since a form cannot read its own status through this hook.

A Common Mistake

function ProfileForm({ updateProfile }) {
  const { pending } = useFormStatus(); // Wrong: always returns pending: false here

  return (
    <form action={updateProfile}>
      <button disabled={pending}>Save</button>
    </form>
  );
}
// Fix: move the useFormStatus call into a child component rendered inside the <form>

Why This Avoids Prop Drilling

Without useFormStatus, showing a pending state on a deeply nested submit button would require passing an isPending prop down manually. useFormStatus reads it directly from the surrounding form context instead, keeping the submit button fully self-contained and reusable across different forms.

Best Practice

Use useFormStatus specifically inside small, reusable components meant to live within a form (submit buttons, inline validation messages) — for the top-level component that renders the form itself, useActionState is usually the better fit for tracking pending/result state.

Interview Questions

Quick Quiz

1. What does useFormStatus let a component read?

2. What happens if useFormStatus is called in the same component that renders the <form> itself?

3. What problem does useFormStatus solve compared to manually passing a pending prop down?