useFormStatus and Form State

By the end of this lesson you'll understand the React 19 useFormStatus hook — how it reads the parent form's pending state from a child, why it must live inside the form, how to build a reusable SubmitButton , and how it relates to useActionState and useOptimistic .

Learn useFormStatus and Form State in our free React course — an interactive lesson with worked examples, a practice exercise and a quick reference.

Part of the free React course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

1. What useFormStatus is

useFormStatus is a React 19 hook from react-dom that gives a component information about the last submission of its parent . It returns an object with pending , data , method , and action . The killer feature: a deeply nested button can know whether the form is submitting without the parent passing a prop down.

2. The reusable SubmitButton pattern

The number-one use case: a SubmitButton that disables itself and shows a spinner while the form is busy. Because it reads pending from context, you can drop the same button into any form. Read every comment in this read-only JSX:

3. The full status object

Beyond pending , the hook exposes data (a FormData of the in-flight fields), method ( "get" or "post" ), and action (the function or URL the form targets). You can read submitted values mid-flight from data :

Run this to see the status object change across a submission's lifecycle — idle, then active — and how a button derives its label from pending alone:

Your turn. A submit button is disabled only while pending and shows "Saving..." in that state. Fill in the two blanks, then run it and check the output.

4. Form actions and Server Actions

In React 19 a can take a function as its action prop. React calls it with the FormData on submit, automatically tracks the pending state (which is what useFormStatus reads), and resets the form on success. In a Server Components setup that function can be a Server Action ( "use server" ), running on the server. Either way, useFormStatus works the same on the client.

5. Pairing with useActionState

useFormStatus only reads status — it doesn't manage the action's result. For that, React 19's useActionState (formerly useFormState in react-dom ) wires the action up and holds whatever it returns (errors, success flags). They compose neatly: useActionState on the form, useFormStatus in the child button.

useFormStatus() — read-only. A child reads the parent form's pending / data / method / action . Best for a reusable SubmitButton.

useActionState(fn, initial) — owns an action and the state it returns. Best for validation errors and results shown next to the form.

useOptimistic(state, updater) — shows a temporary optimistic value while the action is pending, then reconciles. Best for instant UI like "message sent".

Note: useFormState was renamed to useActionState in React 19 and moved from react-dom to react .

Q: Why does my button stay enabled even while submitting?

Either the component reading useFormStatus isn't a child of the form, or your form uses onSubmit instead of a function action . The hook tracks form actions from inside the form.

useFormStatus is imported from react-dom . The related useActionState is imported from react .

No. It works with any function passed to a form's action — a plain client function or a Server Action both work.

It was renamed to useActionState and moved to react in React 19. The behaviour is the same; use the new name.

No blanks this time — just a brief and a starter outline. Write describeStatus(status) that turns the object useFormStatus returns into a sentence. Run it and check your output against the expected lines in the comments.

Practice quiz

What does the React 19 useFormStatus hook give you access to?

  • The pending/data/method/action state of the parent form
  • The browser's network connection state
  • A list of all form validation errors
  • The status of every form on the page

Answer: The pending/data/method/action state of the parent form. useFormStatus reads the status of the last form action submission for the nearest parent form, exposing pending, data, method, and action.

Where must a component that calls useFormStatus be rendered?

  • At the top level of the app
  • Inside a useEffect
  • Inside the form element, as a child
  • On the same component that renders the form element

Answer: Inside the form element, as a child. useFormStatus only returns meaningful status when the component is rendered inside a form, not on the component that renders the form itself.

What does the pending property tell you?

  • How many fields are filled in
  • Whether the form's submission is currently in progress
  • Whether the form has any validation errors
  • Whether the form has been touched

Answer: Whether the form's submission is currently in progress. pending is a boolean that is true while the form's action is running, which is ideal for disabling a submit button.

Which property of useFormStatus contains the submitted form fields?

  • body
  • fields
  • values
  • data

Answer: data. data is a FormData object containing the data the parent form is submitting, or null when not pending.

Why does useFormStatus NOT work when called in the same component that renders the form?

  • It only tracks status of an enclosing parent form, so it returns the default inactive state
  • It requires a useEffect wrapper
  • It needs a ref to the form
  • It throws an error

Answer: It only tracks status of an enclosing parent form, so it returns the default inactive state. The hook reads status from a parent form. In the component that owns the form there is no parent form above it, so it reports no active submission.

What is the most common use case for useFormStatus?

  • Animating form fields
  • Building a reusable SubmitButton that disables itself while pending
  • Validating email addresses
  • Fetching data on mount

Answer: Building a reusable SubmitButton that disables itself while pending. A reusable SubmitButton reads pending and disables itself, so any form can drop it in without managing loading state manually.

Which React feature does useFormStatus pair with to handle submissions?

  • the onSubmit attribute only
  • useReducer
  • the Context API
  • form action functions (and Server Actions)

Answer: form action functions (and Server Actions). useFormStatus tracks the status of a form whose action prop is a function (a client action or Server Action).

How does useActionState differ from useFormStatus?

  • useActionState only works on the server
  • They are identical
  • useActionState manages the action's state and result, while useFormStatus reads pending status from a child
  • useFormStatus replaces useState

Answer: useActionState manages the action's state and result, while useFormStatus reads pending status from a child. useActionState wires up an action and holds its returned state; useFormStatus is a read-only status reader for descendants of the form.

Which hook would you use to show an immediate, optimistic UI update before the action resolves?

  • useRef
  • useOptimistic
  • useMemo
  • useFormStatus

Answer: useOptimistic. useOptimistic lets you show a temporary optimistic value while an async action (often a form action) is pending.

What was useFormStatus's relationship to the older useFormState?

  • useFormState was renamed and replaced by useActionState in React 19
  • useFormStatus replaced useFormState
  • useFormState is the server-only version
  • They are unrelated

Answer: useFormState was renamed and replaced by useActionState in React 19. useFormState (from react-dom) was renamed to useActionState (in react) in React 19; useFormStatus is a separate status-reading hook.