NextJS 13 – Data is not being refetched on router push – Reactjs

by
Liam Thompson
next.js react-typescript reactjs

The Problem:

In a NextJS 13 application, the user list page is not being updated after a user is deleted. The delete user button is making an API call to delete the user, but the user list page (fetched using an external API) is not being refetched after the deletion. The goal is to understand why the user list page is not being refreshed and to find a solution to ensure that the page is updated after a user is deleted.

The Solutions:

Solution 1: Execute revalidate from a route handler or using server actions

The problem was that you were trying to execute the revalidate directly from a Client Component, which is not possible. To execute a revalidatePath / revalidateTag from a Client Component, you have two options:

Option 1: Request a route handler

  1. Create a route handler for the page where you want to perform the revalidation.
  2. In the route handler, call revalidatePath or revalidateTag.

For example, if you want to revalidate the /users page after deleting a user, you could create the following route handler:

export async function handleUsers(req, res) {
  // Revalidate the `/users` page
  await revalidatePath(req, res, '/users')

  // Redirect the user back to the `/users` page
  res.redirect('/users')
}

Option 2: Use server actions

  1. Create a server action for the function you want to execute on the server.
  2. Call the server action from your client component.

For example, you could create the following server action to delete a user:

export async function deleteUser(req, res) {
  // Get the user ID from the request body
  const id = req.body.id

  // Delete the user from the database
  await User.deleteById(id)

  // Revalidate the `/users` page
  await revalidateTag(req, res, 'users')

  // Send a success response
  res.status(200).end()
}

And then you could call the server action from your client component like this:

const deleteUser = async (id) => {
  // Call the server action to delete the user
  await fetch('/api/delete-user', {
    method: 'POST',
    body: JSON.stringify({ id }),
  })

  // Redirect the user back to the `/users` page
  router.push('/users')
}

Both of these options will allow you to execute a revalidate from a Client Component.

Solution 2: Using revalidateTag

The issue is that the `getUsers` function is fetching data from an external API and caching the results. When a user is deleted, the cached data is still being used, so the users list is not being updated. To fix this, you can use the `revalidateTag` function to invalidate the cache for the `users` tag whenever a user is deleted.

const deleteUserCallback = async (id: string) => {
  deleteUser(id)
  .then(() => {
    revalidateTag("users") // Invalidate the cache for the "users" tag
    router.push("/users")
  })
}

This will ensure that the `getUsers` function will fetch fresh data from the API the next time it is called, and the users list will be updated.

Q&A

How to revalidate the cache when a user is created / updated / deleted?

Invalidate the cache using revalidatePath or revalidateTag, or disable caching for the getUsers request.

How to fix the error: Error: Invariant: static generation store missing in revalidateTag users?

This might be a bug on Vercel’s side, see the GitHub issue for more information.

Video Explanation:

The following video, titled "NextJS 13 Tutorial - Routing, Data Fetching, Server Components ...", provides additional insights and in-depth exploration related to the topics discussed in this post.

Play video

NextJS 13 came with a lot of new changes, so I wanted to make this video explaining what is up with the new update.