On-Demand Revalidation Doesn't Work
Answered
Virtue posted this in #help-forum
VirtueOP
app/page.jsx
app/api/revalidate/route.js
update and revalidate
list items
I'm making the item disabled. I checked it from the database. That item is disabled: true. But I'm refreshing the page, I still see that item, which means it fails to revalidate but returns true. I'm very confused. Can anyone help?
Next.js 13.4.19
export default async function Page({ params, searchParams }) {
const res = await fetch(`https://${process.env.NEXT_PRIVATE_URL}/api/item/get`, { next: { tags: ['item'] } })
const data = await res.json() || [];
return <ItemContainer searchParams={searchParams} data={data} />;
}
app/api/revalidate/route.js
import { NextResponse } from "next/server";
import { revalidateTag } from "next/cache";
export async function POST(request) {
const secret = request.nextUrl.searchParams.get("secret");
const tag = request.nextUrl.searchParams.get("tag");
if (secret !== process.env.REVALIDATE_SECRET_KEY) {
return NextResponse.json({ message: "Invalid secret" }, { status: 401 });
}
if (!tag) {
return NextResponse.json({ message: "Missing tag param" }, { status: 400 });
}
revalidateTag(tag);
return NextResponse.json({ revalidated: true, now: Date.now() });
}
update and revalidate
await itemModel.updateOne(
{ uuid: uuidItem },
{ disabled: !item.disabled }
);
const revalidate = await fetch(
`https://${process.env.NEXT_PRIVATE_URL}/api/revalidate?tag=item&secret=${process.env.REVALIDATE_SECRET_KEY}`,
{
cache: "no-cache",
method: "POST",
headers: {
"Content-Type": "application/json",
},
}
);
const revalidateData = await revalidate.json();
console.log(revalidateData); // revalidate: true
list items
{data
.filter((item) => item.disabled === false)
.map((item, index) => (
<Item key={index} item={item} />
))}
I'm making the item disabled. I checked it from the database. That item is disabled: true. But I'm refreshing the page, I still see that item, which means it fails to revalidate but returns true. I'm very confused. Can anyone help?
Next.js 13.4.19
Answered by Virtue
I found the problem, the api/item/get is statically created. The static thing always gives the same value the initial build state, I'll just de-static and it will always give the updated data in the database, thanks, we were trying in vain.
40 Replies
When you make the post request to your revalidation route handler, use the
no-store
cache option.no-cache
and no-store
have two slightly different meanings. If you want to be sure the request doesn't get cached you need to use no-store
.You can read more about these two options here: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control
@not-milo.tsx When you make the post request to your revalidation route handler, use the `no-store` cache option.
`no-cache` and `no-store` have two slightly different meanings. If you want to be sure the request doesn't get cached you need to use `no-store`.
VirtueOP
I made the changes you said. I did no-cache -> no-store but my problem still persists, it still shows disabled:true item when I refresh the page
Are you re-fetching the data after revalidation?
@not-milo.tsx Are you re-fetching the data after revalidation?
VirtueOP
no i didn't do anything like that
app/page.jsx
export default async function Page({ params, searchParams }) {
const res = await fetch("URL", { next: { tags: ['item'] } })
const data = await res.json() || [];
return <ItemContainer searchParams={searchParams} data={data} />;
}
export default async function Page({ params, searchParams }) {
const res = await fetch("URL", { next: { tags: ['item'] } })
const data = await res.json() || [];
return <ItemContainer searchParams={searchParams} data={data} />;
}
Items are listed in the ItemContainer
Also, could you please format your code blocs using the triple backtick so that it is more readable?
VirtueOP
export default async function Page({ params, searchParams }) {
const res = await fetch("URL", { next: { tags: ['item'] } })
const data = await res.json() || [];
return <ItemContainer searchParams={searchParams} data={data} />;
}
Once you revalidate the cached data you need to fetch it again, if you don't then you will not see the update in your UI
@not-milo.tsx Once you revalidate the cached data you need to fetch it again, if you don't then you will not see the update in your UI
VirtueOP
Doesn't it come after just refreshing the page?
@not-milo.tsx Once you revalidate the cached data you need to fetch it again, if you don't then you will not see the update in your UI
VirtueOP
Any chance of giving an example?
I couldn't find anything about bringing the dump page again.
Official Docs:
Official Docs:
export default async function Page() {
const res = await fetch('https://...', { next: { tags: ['collection'] } })
const data = await res.json()
// ...
}
import { NextResponse } from 'next/server'
import { revalidateTag } from 'next/cache'
// e.g a webhook to `your-website.com/api/revalidate?tag=collection&secret=<token>`
export async function POST(request) {
const secret = request.nextUrl.searchParams.get('secret')
const tag = request.nextUrl.searchParams.get('tag')
if (secret !== process.env.MY_SECRET_TOKEN) {
return NextResponse.json({ message: 'Invalid secret' }, { status: 401 })
}
if (!tag) {
return NextResponse.json({ message: 'Missing tag param' }, { status: 400 })
}
revalidateTag(tag)
return NextResponse.json({ revalidated: true, now: Date.now() })
}
As stated by the docs, the
Once you use it, you have to fetch the data again in one way or another.
revalidateTag
method purges the cache entries associated with a particular tag. It doesn't do anything else.Once you use it, you have to fetch the data again in one way or another.
You can trigger a page reload with
router.refresh()
after revalidating for example. Or you could make a new fetch request for your data and update your state variables accordingly.@not-milo.tsx As stated by the docs, the `revalidateTag` method purges the cache entries associated with a particular tag. It doesn't do anything else.
Once you use it, you have to fetch the data again in one way or another.
VirtueOP
Revalidating Data
Revalidation is the process of purging the Data Cache and re-fetching the latest data. This is useful when your data changes and you want to ensure you show the latest information.
Revalidation is the process of purging the Data Cache and re-fetching the latest data. This is useful when your data changes and you want to ensure you show the latest information.
re-fetching the latest data.
Claims to get updated data again
Can you link me the page where you found that?
This is the latest available docs on the topic: https://nextjs.org/docs/app/building-your-application/caching#on-demand-revalidation
And there's no mention of refetching, just cache invalidation.
This is the latest available docs on the topic: https://nextjs.org/docs/app/building-your-application/caching#on-demand-revalidation
And there's no mention of refetching, just cache invalidation.
And where did you read that
revalidateTag
refetches the data for you?VirtueOP
That's just saying what revalidation is, and not what
revalidateTag
or revalidatePath
do@not-milo.tsx That's just saying what revalidation is, and not what `revalidateTag` or `revalidatePath` do
VirtueOP
Now I understand, so what is the most practical way for me?
You are the one responsible for the fetching of your data. Next only provides you the tools to control how it is cached and how to purge/clean said cache.
@Virtue Now I understand, so what is the most practical way for me?
Refresh the page with
router.refresh()
, or make a new fetch request and use the data to update your state variables@not-milo.tsx Refresh the page with `router.refresh()`, or make a new fetch request and use the data to update your state variables
VirtueOP
Is it normal for the items to still appear on the screen when the data is cleared?
I used the revalidate Tag, but the items appear as before when I refresh the page, how can they appear if I clear the cache?
If its cache is deleted, where could it be pulling these items from?
Can you link me the repository where you have this code?
@not-milo.tsx Can you link me the repository where you have this code?
VirtueOP
The code is running on the virtual server, there is no repo, but I can send the source codes you want.
@not-milo.tsx Can you link me the repository where you have this code?
VirtueOP
If you have an example with revalidate Tag, I would like to examine it.
I'll link you an example tomorrow morning. Right now it's getting really late where I live 😅
@not-milo.tsx I'll link you an example tomorrow morning. Right now it's getting really late where I live 😅
VirtueOP
Anytime, thank you very much
VirtueOP
I think there is a problem in my source codes, I set up a server as localhost, I built and started here, when I make a revalidate tag and f5 again on the page, it goes and brings new data.
Really interesting, nothing much when I do it different I just removed the foot on localhost
@not-milo.tsx I'll link you an example tomorrow morning. Right now it's getting really late where I live 😅
VirtueOP
I found the problem, the api/item/get is statically created. The static thing always gives the same value the initial build state, I'll just de-static and it will always give the updated data in the database, thanks, we were trying in vain.
Answer
@Virtue I found the problem, the api/item/get is statically created. The static thing always gives the same value the initial build state, I'll just de-static and it will always give the updated data in the database, thanks, we were trying in vain.
Braque du Bourbonnais
I thought the whole point of ISR is that we don't have to rebuild the static pages when the underlying data changes, and that it will update those parts of our page?
@Braque du Bourbonnais I thought the whole point of ISR is that we **don't have to rebuild** the static pages when the underlying data changes, and that it will update those parts of our page?
Shy Albatross
it's not a static page that was OP's problem, but an API route that got statically optimized so it was always returning the same data