Forms, pending state and server actions

Recently, I was refreshing my Next.js knowledge and thought a good way to do this was to build a form—because everyone loves forms...

I started by using Zod and React Hook Form to create a basic form, but I hit an issue shortly after setting it up. Previously, I would use RTK Query to make a client-side request on form submission. However, this time I wanted to use Server Actions, and I wasn’t sure how to handle the pending state of the request.

RTK Query gives you an isLoading flag out of the box, so creating a loading UI is straightforward. But I had never tried to do the same when making a request via a Server Action.

My solution: useFormStatus()

useFormStatus is a React hook that provides the pending state of a form submission. It’s specifically designed to work with Server Actions and React Server Components.

You can use it like this:

const { pending } = useFormStatus();

Then in your form component, you can use the pending state to show loading indicators or disable buttons:

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

  return (
    <button disabled={pending}>{pending ? "Submitting..." : "Submit"}</button>
  );
}

The pending state will automatically be true while the form is being submitted and false once the submission is complete. This makes it much easier to handle loading states in your forms when using Server Actions.