DEV Community

Cover image for React useFormStatus Hook , Complete Guide (Beginner to Advanced)
Homayoun Mohammadi
Homayoun Mohammadi

Posted on

React useFormStatus Hook , Complete Guide (Beginner to Advanced)

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);
}
Enter fullscreen mode Exit fullscreen mode

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>
  );
}
Enter fullscreen mode Exit fullscreen mode

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>
  );
}
Enter fullscreen mode Exit fullscreen mode

🔍 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();
Enter fullscreen mode Exit fullscreen mode

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>}
    </>
  );
}
Enter fullscreen mode Exit fullscreen mode

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");
  }
}
Enter fullscreen mode Exit fullscreen mode

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

Top comments (0)