React useFormStatus Hook , Complete Guide (Beginner to Advanced)



This content originally appeared on DEV Community and was authored by Homayoun Mohammadi

If you’ve ever worked with forms in React, you already know the pain:

  • How do I know when the form is submitting?
  • Should the submit button be disabled while sending data?
  • How do I show success or error messages after submission?
  • And what if I have multiple forms on the same page , how do I manage each one’s state separately?

Before React 19, all of this required several useState hooks, conditional logic, and a lot of boilerplate code.

But now, with the useFormStatus hook, you can handle form states in a much cleaner and simpler way , especially when working with Server Actions in frameworks like Next.js 13+.

🚀 What Is useFormStatus in React?

The useFormStatus hook is a built-in React hook designed specifically for Server Actions.

It helps you track the current status of a form , whether it’s being submitted, what data was sent, which method was used, and more.

Property Description
pending Returns true when the form is currently submitting
data The form data submitted by the user
method The HTTP method used (POST, GET, etc.)
action The action function or endpoint handling the form

⚠ Important:

useFormStatus only works inside a form boundary.

If you use it outside a <form> tag, pending will always return false.

⚙ Prerequisites

To use useFormStatus, make sure:

  1. You’re using React 18.3 or higher
  2. Your app supports Server Actions (like in Next.js 13+)
  3. Your form action is defined on the server using "use server"

🧠 Example: Using useFormStatus in React

1. Create a Server Action

// title="app/actions.ts"
"use server";

export async function createUser(formData: FormData) {
  const name = formData.get("name") as string;

  // Simulate network delay
  await new Promise((r) => setTimeout(r, 2000));

  console.log("User created:", name);
}

2. Create a Submit Button with useFormStatus

"use client";

import { useFormStatus } from "react-dom";

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

  return (
    <button
      type="submit"
      disabled={pending}
      className="px-4 py-2 bg-blue-600 text-white rounded"
    >
      {pending ? "Submitting..." : "Register"}
    </button>
  );
}

3. Build the Main Form

import { createUser } from "./actions";
import { SubmitButton } from "./SubmitButton";

export default function Page() {
  return (
    <form action={createUser} className="space-y-4">
      <input
        type="text"
        name="name"
        placeholder="Name"
        className="border p-2 rounded w-full"
      />
      <SubmitButton />
    </form>
  );
}

🔍 Advanced Tips for useFormStatus

1. Multiple Forms on One Page

Because useFormStatus works within its own form boundary, each form manages its own state.

So if you have two forms, pressing one submit button won’t affect the other , no more accidental button disabling!

2. Access More Form Data

const { pending, data, method, action } = useFormStatus();

You can use these values to:

  • Log submitted form data
  • Track the submission method (POST, GET, etc.)
  • Debug which action handled the form

3. Show Success or Error Messages

"use client";
import { useState } from "react";
import { useFormStatus } from "react-dom";

export function SubmitButtonWithMessage() {
  const { pending } = useFormStatus();
  const [done, setDone] = useState(false);

  return (
    <>
      <button
        type="submit"
        disabled={pending}
        onClick={() => setDone(false)}
        className="px-4 py-2 bg-green-600 text-white rounded"
      >
        {pending ? "Sending..." : "Send"}
      </button>
      {done && <p className="text-green-600 mt-2"> Submission successful!</p>}
    </>
  );
}

You can call setDone(true) after your server action completes (for example, after a redirect or mutation).

4. Server-Side Validation Example

Combine useFormStatus with server-side validation for a cleaner and safer UX:

"use server";

export async function registerUser(formData: FormData) {
  const email = formData.get("email") as string;

  if (!email.includes("@")) {
    throw new Error("Invalid email address");
  }
}

This ensures validation happens securely on the server while keeping the frontend simple.

5. Improve UX During Submission

When pending is true:

  • Disable the submit button
  • Show a loading spinner
  • Make form inputs read-only

This keeps users informed and prevents double submissions.

🧾 Summary

The useFormStatus hook in React simplifies form management by letting you access the form’s submission state directly within its boundary , no need for extra useState logic.

Benefits:

  • Cleaner and more maintainable code
  • Independent form states
  • Better UX with instant feedback
  • Perfect for Next.js and React Server Actions


This content originally appeared on DEV Community and was authored by Homayoun Mohammadi