revalidateTag doesn't seem to be working
Answered
Cimarrón Uruguayo posted this in #help-forum
Cimarrón UruguayoOP
For the route /work i have a corresponding component where the relevant section is in the first screenshot. The CMS has a hook that gets triggered to perform the revalidation.
However, when I make the change to any document on the CMS, and then go back to /work and refresh, the relevant content wrapped in unstable_cache does not get updated, and the previous cached data is reused. What could the issue be? Please let me know if any more information is required if you haven't fully understood my scenario.
import type { CollectionAfterChangeHook } from 'payload'
import { revalidateTag } from 'next/cache'
import type { CaseStudy } from '@/payload-types'
export const revalidateTagged: CollectionAfterChangeHook<CaseStudy> = ({
doc,
previousDoc,
req: { payload },
}) => {
if (doc._status === 'published') {
const tag = 'case-studies'
payload.logger.info(`Revalidating tag: ${tag}`)
revalidateTag(tag)
}
return doc
}However, when I make the change to any document on the CMS, and then go back to /work and refresh, the relevant content wrapped in unstable_cache does not get updated, and the previous cached data is reused. What could the issue be? Please let me know if any more information is required if you haven't fully understood my scenario.
Answered by joulev
const getBooks = unstable_cache(
async () => {
const payload = await getPayloadHMR({ config })
const books = await payload
.find({ collection: 'books', pagination: false })
.then(({ docs }) => docs)
return books
},
[],
{ tags: ["books"] },
)78 Replies
@Cimarrón Uruguayo For the route /work i have a corresponding component where the relevant section is in the first screenshot. The CMS has a hook that gets triggered to perform the revalidation.
ts
import type { CollectionAfterChangeHook } from 'payload'
import { revalidateTag } from 'next/cache'
import type { CaseStudy } from '@/payload-types'
export const revalidateTagged: CollectionAfterChangeHook<CaseStudy> = ({
doc,
previousDoc,
req: { payload },
}) => {
if (doc._status === 'published') {
const tag = 'case-studies'
payload.logger.info(`Revalidating tag: ${tag}`)
revalidateTag(tag)
}
return doc
}
However, when I make the change to any document on the CMS, and then go back to /work and refresh, the relevant content wrapped in unstable_cache does not get updated, and the previous cached data is reused. What could the issue be? Please let me know if any more information is required if you haven't fully understood my scenario.
does it work when you refresh after some time (say, a few seconds)?
iirc this falls into the category of background refreshes, where the item is revalidated in the background and visitors continue to see the outdated content until the refresh is complete.
iirc this falls into the category of background refreshes, where the item is revalidated in the background and visitors continue to see the outdated content until the refresh is complete.
i have a similar set up and it works fine no issues https://github.com/joulev/website/blob/73bcb8d93eebbc1c278fad980f799931972e0e28/src/app/(public)/apps/irasuto/add/route.ts#L99
@joulev does it work when you refresh after some time (say, a few seconds)?
iirc this falls into the category of background refreshes, where the item is revalidated in the background and visitors continue to see the outdated content until the refresh is complete.
Cimarrón UruguayoOP
i haven't set any revalidate constants on the page.tsx
that's not really related to this case, no
Cimarrón UruguayoOP
nope it doesn't resolve after refreshing either
ill see if i can make you a minimal reproducible repo to play with
because im quite lost on this issue atm 😅
yes that will help
@joulev yes that will help
Cimarrón UruguayoOP
nearly done, just another 10 mins
Asari
Hello , I am having a problem with revalidatepath, can you help me with this?
Cimarrón UruguayoOP
@joulev there's a little bit of boilerplate, but i've stripped off as much as i can
should i make a github repo for this?
yep that will help
thanks, will clone and check
Cimarrón UruguayoOP
the code of interest is mainly going to be
src/payload.config.ts, src/app/(frontend)/books and src/collections/Books@joulev thanks, will clone and check
Cimarrón UruguayoOP
can u clone again pls
just updated
last time sorry
should be allg now :D
@Cimarrón Uruguayo can u clone again pls
could you make it not depend on payload? i don't have a payload account
ideally it should run on its own no need of env vars
like take current time for example instead of payload data
@joulev could you make it not depend on payload? i don't have a payload account
Cimarrón UruguayoOP
you don't need one
its all headless
payload is inbuilt into the nextjs app
i see
Cimarrón UruguayoOP
yeah its a very cool cms
Cimarrón UruguayoOP
the issue is that uh
when I create a book on the cms
like so,
and refresh the page again on /books
still don't see any updates
even though i've supposedly called revalidateTag
@Cimarrón Uruguayo yeah its a very cool cms
well to see why this doesn't work i need to know where the
the
so yeah i don't know, sorry. if you could reproduce this without payload that would be great.
afterOperation hook is run, for which i have no idea since i never used this cms.the
revalidateTag call has to be run in a route handler or a server action for it to work. (note that "use server" doesn't mean it will be run as a server action.)so yeah i don't know, sorry. if you could reproduce this without payload that would be great.
thank you so much for the effort tho 🔥
appreciate it
@joulev well to see why this doesn't work i need to know where the `afterOperation` hook is run, for which i have no idea since i never used this cms.
the `revalidateTag` call has to be run in a route handler or a server action for it to work. (note that `"use server"` doesn't mean it will be run as a server action.)
so yeah i don't know, sorry. if you could reproduce this without payload that would be great.
Cimarrón UruguayoOP
by "where" do you mean client/server
if
revalidateTag was run in the client it would throw an error. i was thinking about payload running it in a weird after-process or something like that, where revalidateTag cannot access the cache store to tell nextjs to revalidate@joulev if `revalidateTag` was run in the client it would throw an error. i was thinking about payload running it in a weird after-process or something like that, where `revalidateTag` cannot access the cache store to tell nextjs to revalidate
Cimarrón UruguayoOP
ok i got it to work... but its a very weird fix
const getBooks = async () => {
const payload = await getPayloadHMR({ config })
const books = await payload
.find({ collection: 'books', pagination: false })
.then(({ docs }) => docs)
return books
}
const cachedGetBooks = unstable_cache(
async () => getBooks(),
['books'],
{ tags: ['books'] }
)
const Page = async () => {
const books = await cachedGetBooks()
// rest of component
}w-wha
Cimarrón UruguayoOP
i have no idea why that worked 😭
oh i see why it didn't work now
i was dang stupid
Cimarrón UruguayoOP
hmm?
didn't see the clearest thing
Cimarrón UruguayoOP
please explain to me 🙏
const getBooks = unstable_cache(
async () => {
const payload = await getPayloadHMR({ config })
const books = await payload
.find({ collection: 'books', pagination: false })
.then(({ docs }) => docs)
return books
},
['books']
)here you never declared any tags
you just declared "books" as a key which is not a tag
Cimarrón UruguayoOP
was that necessary?
the docs is kind of confusing on this
const getBooks = unstable_cache(
async () => {
const payload = await getPayloadHMR({ config })
const books = await payload
.find({ collection: 'books', pagination: false })
.then(({ docs }) => docs)
return books
},
[],
{ tags: ["books"] },
)Answer
this should work
note the line
{ tags: ["books"] }Cimarrón UruguayoOP
right
but what's the distinction between key and tag
oh is the tag like the actual cache lookup key
@Cimarrón Uruguayo but what's the distinction between key and tag
different key then it will be revalidated, so it's like
it will be revalidate when wednesday comes and when thursday comes
const isWednesday = ...
const getBooks = unstable_cache(
async () => ...,
[isWednesday ? "wed" : "not-wed"],
)it will be revalidate when wednesday comes and when thursday comes
but it is not a tag so
revalidateTag("wed") and such doesn't work because nextjs doesn't know this tag@joulev but it is not a tag so `revalidateTag("wed")` and such doesn't work because nextjs doesn't know this tag
Cimarrón UruguayoOP
ok I have understood this part
sorry
actually ill just mark it as solved and study this a little more thoroughly, MASSIVELY appreciate your help
@Cimarrón Uruguayo not following here, unfortunately
yeah it's quite rare but i remember it was necessary for me at least once, lemme check back where i used it
@Cimarrón Uruguayo not following here, unfortunately
async function getData(query: string) {
console.log("this is run once for each unique value of `query`");
// ...
}
async function Page({ searchParams }) {
const query = searchParams.query;
const data = await unstable_cache(
() => getData(query),
[query]
)();
// ...
}for a different value of
query, it will be rerun again since the key has changedfor the same value of
query, it will serve the result from the cache and not rerun getData againCimarrón UruguayoOP
oh so its like mini cache slots
yeah
Cimarrón UruguayoOP
oooh that's cool
so if a specific query fills the slot
then the next time its fetched, it'll get read from there
thank you for the explanation
you have a few revalidation methods:
* change the
* force-revalidate with
* change the
key by using the keyParts array or changing the function string (callback.toString())* force-revalidate with
revalidateTag then it will revalidate even when the key remains the same@joulev different key then it will be revalidated, so it's like
tsx
const isWednesday = ...
const getBooks = unstable_cache(
async () => ...,
[isWednesday ? "wed" : "not-wed"],
)
it will be revalidate when wednesday comes and when thursday comes
so in this example, when it becomes wednesday, the key changes so it is rerun again.
for the rest of the wednesday, the key never changes so the data is served from cache.
when thursday comes, the key changes again and the data is rerun again.
the data would then be cached until the next wednesday comes.
for the rest of the wednesday, the key never changes so the data is served from cache.
when thursday comes, the key changes again and the data is rerun again.
the data would then be cached until the next wednesday comes.
Cimarrón UruguayoOP
yeah its starting to click now :)
i doubt you will need this keypart a lot. my work app has many
but yeah just remember the keypart array is not where you declare the tags. you declare the tags in
unstable_cache and all of them have an empty keypart array.but yeah just remember the keypart array is not where you declare the tags. you declare the tags in
{ tags: ... }