Suggest an editImprove this articleRefine the answer for “What is useFormStatus?”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**`useFormStatus()`** is a React hook that provides the current state of a form tied to an Action: whether the submit is running (`pending`), what data was submitted (`data`), which method (`method`), and which Action function is attached (`action`). **Key point:** the hook works only inside descendants of a `<form>` and lets you build reusable button and indicator components without manual `useState`/`isLoading`.Shown above the full answer for quick recall.Answer (EN)Image## What `useFormStatus()` is > `useFormStatus()` is a React hook that provides the **current state of a form** tied to an **Action**. > It reports whether the submit is running (`pending`), what data was submitted (`data`), whether there is an error (`error`), and so on. Put simply: `useFormStatus()` gives you **access to the state of the form itself**, similar to how `useActionState()` manages the state of an Action. --- ## Syntax ```javascript const { pending, data, method, action } = useFormStatus(); ``` | Field | Description | |---|---| | `pending` | `true` while the form is running the Action (an analog of `isSubmitting`) | | `data` | A `FormData` object with the submitted data | | `method` | The form's method (`GET`, `POST`, etc.) | | `action` | A reference to the Action function attached to the form | --- ## How it works React 19 now understands `<form>` as a *managed element*: - On submit, React automatically calls the Action (server or client); - While the Action is running, React updates `useFormStatus()` inside that form; - Components nested in the form can read this state and show, for example, a spinner or an error message. --- ## Example: a form loading indicator ```javascript import { useActionState, useFormStatus } from 'react'; async function sendMessage(prev, formData) { const message = formData.get('message'); await api.send(message); return { success: true }; } function SubmitButton() { const { pending } = useFormStatus(); return ( <button type="submit" disabled={pending}> {pending ? 'Sending...' : 'Send'} </button> ); } export default function ChatForm() { const [state, formAction] = useActionState(sendMessage, null); return ( <form action={formAction}> <input name="message" /> <SubmitButton /> {state?.success && <p>Message sent!</p>} </form> ); } ``` Here: - `useFormStatus()` runs inside `SubmitButton`, but it automatically knows that it belongs to the form where `action={formAction}` is specified; - `pending` becomes `true` on submit, and React updates the button; - all of this without manual `useState` and `setLoading`. --- ## Features of `useFormStatus` #### 1. Works only **inside descendants** of `<form>` The hook gets the form's context from the nearest parent: ```javascript function MyButton() { const { pending } = useFormStatus(); // works only if inside a <form> ... } ``` If called outside a `<form>`, it returns an "empty" state (`pending = false`, etc.). --- #### 2. Works with **Server Actions** and **Client Actions** ```javascript <form action={myServerAction}> ... </form> ``` or ```javascript const [state, formAction] = useActionState(myClientAction, initial); <form action={formAction}>...</form> ``` In both cases `useFormStatus()` tracks the execution status of that Action. --- #### 3. Lets you build reusable button and indicator components For example: ```javascript function SubmitButton({ children }) { const { pending } = useFormStatus(); return ( <button disabled={pending}> {pending ? 'Loading...' : children} </button> ); } ``` Now this button can be used in every form without extra logic. --- #### 4. Supports optimistic UI patterns You can show temporary states (for example, clearing fields, adding a "message sent" note) while the Action is running. --- #### 5. Works with any form method (`GET`, `POST`, etc.) React passes `method` and `data` into `useFormStatus()`, so you can use them in the UI when needed. --- ## Difference from `useActionState()` | Hook | Where it is used | What it provides | |---|---|---| | `useActionState()` | In the component where the Action is declared | Manages the Action's state (errors, result, pending) | | `useFormStatus()` | Inside descendants of `<form>` | Provides the status of the form itself (`pending`, `data`, `method`) | | **Typical role** | Submit logic and data updates | Displaying state (buttons, indicators, fields) | They often work **as a pair**: `useActionState()` manages the action, and `useFormStatus()` manages the form's visual state. --- ## A combined example ```javascript async function updateEmail(prev, formData) { const email = formData.get('email'); await api.updateEmail(email); return { success: true }; } function EmailForm() { const [state, formAction] = useActionState(updateEmail, null); const { pending } = useFormStatus(); return ( <form action={formAction}> <input name="email" /> <button disabled={pending}> {pending ? 'Saving...' : 'Save'} </button> {state?.success && <p>Email updated!</p>} </form> ); } ``` --- ## A more advanced example (separate components) ```javascript function FormField({ label, name }) { const { pending } = useFormStatus(); return ( <div className={pending ? 'disabled' : ''}> <label>{label}</label> <input name={name} disabled={pending} /> </div> ); } function SaveButton() { const { pending } = useFormStatus(); return ( <button disabled={pending}> {pending ? 'Saving...' : 'Save'} </button> ); } function SettingsForm() { const [state, formAction] = useActionState(saveSettings, null); return ( <form action={formAction}> <FormField label="Username" name="username" /> <FormField label="Email" name="email" /> <SaveButton /> {state?.success && <p>Saved!</p>} </form> ); } ``` All the fields and the button automatically know that the form is running, without props, context, or `isLoading`. --- ## Summary > `useFormStatus()` is a new React 19 hook > that lets any component inside a `<form>` know > that the form is running an asynchronous action, and react to it. #### Key advantages: - No manual `isLoading` state or `useState`; - Works with both client and server Actions; - Simplifies writing buttons, spinners, disabled logic; - Lets you build **universal, reusable forms**; - Deeply integrated with `useActionState()`.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.