How to refresh your data using Server Actions and Drizzle in Next.js

When submitting a form using Server Actions, we often want to display the up-to-date data on the screen. For example, if we submit a form to create a new user, we want to show the new user on the screen. Or, if we are updating a user, we want to display the updated user on the screen. Let's have a quick look at how we can do that in Next.js.

A form with Server Actions and Drizzle

Let's say we have a form to create a new user. Next to the form, we have a list of users. When we submit the form, we want to display the new user in the list. It will not happen by default; we must intentionally refresh the data. The reason the list will not refresh is that Next.js is Caching the Data. This helps to make the app faster since we fetch the data at build time or request time and reuse it on each subsequent request.

Using Server Actions with Drizzle, our form would look like this:

// app/actions.ts

'use server'

import { db } from '@/db'
import { users } from '@/db/schema/users'
import { z } from 'zod'

export async function createUser(formData: FormData) {
  const schema = z.object({
    username: z.string().min(3).max(20),
  })

  const data = schema.parse(Object.fromEntries(formData.entries()))

  await db.insert(users).values({
    username: data.username,
  })
}
// app/components/user-form.tsx

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

export function UserForm() {
  return (
    <form action={createUser}>
      <input name="username" />
      <button type="submit">Add user</button>
    </form>
  )
}

On-demand Revalidation

To have the list refreshing, we have two options: opt out of caching or revalidate the data. For our case we'll use the second option.

When it comes to revalidating data, Next.js offers two options: Time-based revalidation and On-demand revalidation. We want to refresh the list eagerly and we'll go with the second option.

We can revalidate the data on-demand using one of the revalidatePath or revalidateTag functions. In our example, we'll go with the revalidatePath() as it's a simple scenario. We need to call it within the server action once we save the data:

// app/actions.ts

'use server'

import { db } from '@/db'
import { users } from '@/db/schema/users'
import { z } from 'zod'
import { revalidatePath } from 'next/cache'

export async function createUser(formData: FormData) {
  const schema = z.object({
    username: z.string().min(3).max(20),
  })

  const data = schema.parse(Object.fromEntries(formData.entries()))

  await db.insert(users).values({
    username: data.username,
  })

  revalidatePath('/')
}

Next steps

Read the Next.js docs on the Data cache, understand how it works and what are the options and standard practices to refresh the data.

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