I have a delete user button on my user page (route: /users/) who call the delete user api’s route.
Then after this call, i execute a router.psuh('/users')
to go back to my users list
But my /users
page is like cached and the data is not re fetched.
This is my delete user button :
"use client"
import deleteUser from "@/lib/users/deleteUser"
import { revalidatePath } from "next/cache"
import { useRouter } from 'next/navigation'
type Props = {
user: User
}
export default function DeleteUserButton({ user }: Props) {
const router = useRouter()
const deleteUserCallback = async (id: string) => {
deleteUser(id)
.then(() => {
router.push("/users")
})
}
return (
<button type="button" onClick={() => deleteUserCallback(user.id)}>
Delete
</button>
)
}
My user page :
import getUserByUsername from "@/lib/users/getUserByUsername"
import DeleteUserButton from "./components/DeleteUserButton"
type Props = {
params: {
username: string
}
}
export async function generateMetadata({ params: { username } }: Props) {
const user = await getUserByUsername(username)
if (user === null) {
return {
title: "User not found",
}
}
return {
title: `${user.lastName} ${user.firstName}`,
}
}
export default async function UserPage({ params: { username } }: Props) {
const user = await getUserByUsername(username)
if (user === null) {
return <div>User not found</div>
}
return (
<div>
<p>User: {user.email}</p>
<DeleteUserButton user={user} />
</div>
)
}
And then my users page :
import getUsers from "@/lib/users/getUsers"
import Link from "next/link"
export default async function UsersPage() {
const usersReq = await getUsers()
const users = usersReq.users
return (
<div>
{users.map((user) => {
return (
<p key={user.id}>
<Link href={`/users/${user.username}`}>
{user.username}
</Link>
{user.firstName}
</p>
)
})}
</div>
)
}
Idk if i have to change my fetch users list method ?
UPDATE
My getUsers function (i’m using an external API):
export default async function getUsers():
Promise<{
users: User[],
pagination: Pagination
}>
{
const res = await fetch(process.env.NEXT_PUBLIC_API_BASE_URL + '/users?pageSize=20', {
cache: 'no-cache',
});
if (!res.ok)
throw new Error('Error fetching');
return res.json();
}
If i add a tag with a revalidateTag it looks like this :
(getUsers)
export default async function getUsers():
Promise<{
users: User[],
pagination: Pagination
}>
{
const res = await fetch(process.env.NEXT_PUBLIC_API_BASE_URL + '/users?pageSize=20', {
cache: 'no-cache',
next: {
tags: ['users']
}
});
if (!res.ok)
throw new Error('Error fetching');
return res.json();
}
And now my DeleteUserButton component :
"use client"
import deleteUser from "@/lib/users/deleteUser"
import { revalidateTag } from "next/cache"
import { useRouter } from 'next/navigation'
type Props = {
user: User
}
export default function DeleteUserButton({ user }: Props) {
const router = useRouter()
const deleteUserCallback = async (id: string) => {
deleteUser(id)
.then(() => {
revalidateTag("users")
router.push("/users")
})
}
return (
<button type="button" onClick={() => deleteUserCallback(user.id)}>
Delete
</button>
)
}
But now i get this error when i click on the delete button :
2
Answers
I was trying to execute the
revalidate
directly from aClient Component
that is seems to be not possible.To execute a
revalidatePath
/revalidateTag
from aClient Component
:And now it works ! ;)
You need to invalidate the cache when a user is created / updated / deleted, or disable it for
getUsers
altogether:Invalidate the cache on demand for a path using
revalidatePath
or for a tag usingrevalidateTag
.Disable the cache altogether for that individual
fetch
request withfetch('https://...', { cache: 'no-store' })
.You can read more about this in the official documentation.
Edit:
About the error you are getting:
This might be a bug on Vercel’s side, see this GitHub issue.