How to clear your forms when using Server Actions in Next.js

The most common use for Server Actions is with forms. Using the HTML form element is the traditional approach to mutating data. Let's look at how we can use Server Actions with forms and clear the form after submitting it.

1. Conventions

Before moving forward, I want to clarify the convention for using Server Actions with Components. There's a distinction between its usage with Server Components and Client Components.

Server Actions with Server Components

With Server Components, the action can be inlined and used with the "use server" directive, placed at the top of the action body:

// app/components/form.tsx

// Server Component
export function Form() {
  // Server Action
  async function submit() {
    'use server'

    // ...
  }

  return <form action={submit}>{/* ... */}</form>
}

We can also define the action outside of the component and import it. In this case, we don't need to use the "use server" directive inside the function body but at the top of the action file:

// app/actions.ts

'use server'

export async function submit() {
  // ...
}
// app/components/form.tsx

import { submit } from '@/app/actions'

export function Form() {
  return <form action={submit}>{/* ... */}</form>
}

Server Actions with Client Components

In this case, the action is defined outside of the component and imported. We need to use the "use server" directive at the top of the file:

// app/actions.ts

'use server'

export async function submit() {
  // ...
}
// app/components/form.tsx

// Client Component

'use client'
import { submit } from '@/app/actions'

export function Form() {
  return <form action={submit}>{/* ... */}</form>
}

2. A simple form with Server Actions

Let's create a simple form that uses Server Actions to submit the data to the server. For the sake of this example, we will return the data in the action. In a real-world scenario, you may want to mutate the data on the server, like creating/updating a record in the database. Our form will have a single input field for the username and a submit button. It is a Server Component, so the action is inlined and uses the "use server" directive.

// app/components/form.tsx

export function Form() {
  async function submit(formData: FormData) {
    'use server'

    const username = formData.get('username')

    return username
  }

  return (
    <form action={submit}>
      <input name="username" />
      <button type="submit">Submit</button>
    </form>
  )
}

3. Resetting the form

After submitting the form, we want to clear the value entered. We can do that using the reset method on the form element. We can access the form element using the useRef hook and define it on the form element. It will return the form object that contains the reset method, and we'll be able to call it in the action. As with any hooks, we can only use them in Client Components, so we need to mark our component as a Client Component by using the "use client" directive. We must also move our action to a separate file and import it.

// app/actions.ts

'use server'

export async function submit(formData: FormData) {
  const username = formData.get('username')

  return username
}
// app/components/form.tsx

'use client'

import { submit } from '@/app/actions'
import { useRef } from 'react'

export function Form() {
  const ref = useRef<HTMLFormElement>(null)

  return (
    <form
      ref={ref}
      action={async (formData) => {
        await submit(formData)
        ref.current?.reset()
      }}
    >
      <input name="username" />
      <button type="submit">Submit</button>
    </form>
  )
}

This way, we get the best of both worlds, using Server Actions with Client Components to reset the form. We can use the same pattern to deal with other form-related tasks, like showing a loading indicator or disabling the submit button while the action is running. Similarly, we can refresh the data using revalidateTag or revalidatePath or redirect to another route.

Subscribe for more like this!

Drop your email below and I'll send you new stuff to your inbox!

No spam, ever. I respect your email privacy. Unsubscribe anytime.

Read more similar articles