Next.js Discord

Discord Forum

On-Demand Revalidation Doesn't Work

Answered
Virtue posted this in #help-forum
Open in Discord
Avatar
app/page.jsx
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.
View full answer

40 Replies

Avatar
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
Avatar
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
Avatar
Are you re-fetching the data after revalidation?
Avatar
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} />;
}
Items are listed in the ItemContainer
Avatar
Also, could you please format your code blocs using the triple backtick so that it is more readable?
Avatar
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} />;
}
Avatar
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
Avatar
Doesn't it come after just refreshing the page?
Any chance of giving an example?
I couldn't find anything about bringing the dump page again.

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() })
}
Avatar
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.
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.
Avatar
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.
re-fetching the latest data.
Claims to get updated data again
Avatar
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.
Avatar
And where did you read that revalidateTag refetches the data for you?
Avatar
Image
Avatar
That's just saying what revalidation is, and not what revalidateTag or revalidatePath do
Avatar
Now I understand, so what is the most practical way for me?
Avatar
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.
Refresh the page with router.refresh(), or make a new fetch request and use the data to update your state variables
Avatar
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?
Avatar
Can you link me the repository where you have this code?
Avatar
The code is running on the virtual server, there is no repo, but I can send the source codes you want.
If you have an example with revalidate Tag, I would like to examine it.
Avatar
I'll link you an example tomorrow morning. Right now it's getting really late where I live 😅
Avatar
Anytime, thank you very much
Avatar
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
Avatar
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
Avatar
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?
Avatar
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