Next.js Discord

Discord Forum

When using app dir, navigating back to server rendered page shows stale results

Answered
possibilities posted this in #help-forum
Open in Discord
I have an app that renders a list of items on the server and then, via a realtime connection to supabase, updates the the list when new items are inserted. When I click on one of the new items to view the details (served at a child segment) and then navigate back I get the stale server rendered version of the page.

I think revalidate = 0 should solve this but I also tried dynamic = 'force-dynamic' and it doesn't help.

Can anyone point out what I'm getting wrong here?

https://github.com/possibilities/next-js-app-dir-realtime
Answered by aardani
You aren't getting it wrong.
Navigations are cached in the client-side for 30seconds.
This is stored in the [router cache](https://nextjs.org/docs/app/building-your-application/caching#router-cache) and [you can't opt-out of it](https://nextjs.org/docs/app/building-your-application/caching#opting-out-3)

### solution
one of the way to work around this is by using a client-side state management like RQ or useSWR. This will make sure your data will get refetched at component mount.

other ways include using router.refresh() (forching hard refresh on load)
or revalidatePath/Tag but this will use up your revalidation quota at vercel
View full answer

42 Replies

@possibilities I have an app that renders a list of items on the server and then, via a realtime connection to supabase, updates the the list when new items are inserted. When I click on one of the new items to view the details (served at a child segment) and then navigate back I get the stale server rendered version of the page. I _think_ `revalidate = 0` should solve this but I also tried `dynamic = 'force-dynamic'` and it doesn't help. Can anyone point out what I'm getting wrong here? https://github.com/possibilities/next-js-app-dir-realtime
You aren't getting it wrong.
Navigations are cached in the client-side for 30seconds.
This is stored in the [router cache](https://nextjs.org/docs/app/building-your-application/caching#router-cache) and [you can't opt-out of it](https://nextjs.org/docs/app/building-your-application/caching#opting-out-3)

### solution
one of the way to work around this is by using a client-side state management like RQ or useSWR. This will make sure your data will get refetched at component mount.

other ways include using router.refresh() (forching hard refresh on load)
or revalidatePath/Tag but this will use up your revalidation quota at vercel
Answer
Thanks, trying to take this all in...

Navigations are cached in the client-side for 30seconds.

If I understand you correctly then if I wait 30 seconds before navigating back I would expect to see fresh content but it doesn't seem to be.
really?
do note that the navigation is cached for every navigation
so it reset the time everytime you click to navigate
Yeah, definitely, waiting has the same result
I'm clicking the back button if that matters
Works just like the gif on my repo
HMMMMMMMMM
ok i just saw the gif
the cache is from before you add the posts
try <Link prefetch={false}>
On the link to the "post detail" page?
yeah
it prefetch the content of the "post detail" but at the same time the cached version of the "Before page" is cached
This is making me feel like I should skip server components for this app. I'm following the way that supabase is suggesting to split apps that have realtime between server/client components and it's really attractive from a code POV but if it's not really going to work without a bunch of fuss I'll probably just avoid server components for now and stick with useSWR.
I wonder if I used server actions and called revalidatePath I'd get the behavior I want
id rather not use revalidateXY since it will use your revalidation quota over at vercel and i dont think its a viable solution tbh
so SSR is only for initial data/first-time load
Cool good to know, I had no idea it worked that way. Sounds similar to (or actually) AWS Cloudfront invalidations
BUT you don't need to if you don't want to
its just a way to prevent content flash
It's cool that we can integrate useSWR with data fetched by server components but I do look forward to the dream that it looks like we can already almost get from SC where everything that I'm going to have to do manually with useSWR is handled by the framework.
yep indeed, we are getting there surely
you can still use server action with useSWR/RQ so it plays nicely too
only that it returns data not SC
(for now?)
Cool, thanks for walking me through all this, going to start working it out
European sprat
@possibilities if you're curious, there's a very popular GitHub issue about this topic https://github.com/vercel/next.js/issues/42991
@European sprat <@850800603868692490> if you're curious, there's a very popular GitHub issue about this topic https://github.com/vercel/next.js/issues/42991
Cool thanks. Is it safe to assume that also affects back button navigation even though the topic is about link?
European sprat
yes
that thread is basically all about the router cache in general at this point
American Crocodile
Actually I’ve been having problems with cache revalidation as well
I tried using swr but it didn’t work as well
When I switched back to the pages version, things seem to be resolved…
Asian black bear
Is the next team working on a solution to opt out of that 30s router cache?
For my specific case I found a workaround that I like: in the supabase subscription callback I call router.refresh()
I like it temporarily anyway. Way better than having to introduce a data fetching/caching library and changing lots of things
Im glad it worked out for you
Polar bear
Just FYI, if you use Server Actions (Experimental/Alpha) for mutation with revlidatePath, it works and you don't need to call
router.refersh()
. (https://nextjs.org/docs/app/building-your-application/caching#invalidation-1)
@European sprat <@850800603868692490> if you're curious, there's a very popular GitHub issue about this topic https://github.com/vercel/next.js/issues/42991
Philippine Crocodile
I just spent 30 minutes reading this and I am still confused, is there literally no way to just block rendering until the data is fresh again? I just want a 5 second cache without the first request being extremely outdated 😭😭😭
Philippine Crocodile
bump please