react-query doesn't use the client cache from the useInfiniteQuery when routing to the same link
I'm using the latest next.js (14.1.0) app router for the project. I used queryclient.prefetchInfiniteQuery on the server to get the data (12 posts) I wanted on route /blogs/page.tsx and hydrated the client component inside this server component with <Hydrationboundary>. Then I used useInfiniteQuery to fetch the data (6 posts) on client as client interacts. Now this works perfetctly for most part, I get prefetched data from server to be loaded on first render and subsequent data fetch on client side with client interaction and I even get the scroll restoration working perfectly fine. BUT I encountered a problem
I clicked on <Link> (from next.js) from the blogs page to go back to home and then click on <Link> towards the blogs page, now the entire cache is gone, the data that got rendered was the data I prefetched from server components just like the first time. I tried to find what was wrong, the code works perfectly fine with cache persisting when I removed prefetching on server and only fetched from client side. Adding prefetch on server created all the problem but now I'm left confused, what really went wrong? I really want to use the prefetch on server.
9 Replies
yelping-magenta•2y ago
Probably the prefetch runs again and overrides the current cache
You can either cache the RSC output somehow, or e.g. put the current page into the url and prefetch more pages on the server. prefetchInfiniteQuery supports that
genetic-orangeOP•2y ago
I tested by adding console.count() on the RSC, I can see that it rerenders and thats what is making this whole problematic. Is this an issue with next.js router cache? or is this an issue with react-query? I would like to make an issue. Also if there is an issue pointing to this can someone point out. This seems soo basic to be working but its not working
I don't wish to prefetch more than 12 blogs when I first land, also this is a common pattern across many different routes. If prefetching on server is a bad solution in the first place when client components are nested inside, I really don't see the value in next.js app router and the whole RSC.
yelping-magenta•2y ago
i think this is per design on both accounts. For normal queries, the re-execution of the RSC would act like a refetch and would just give you fresh data. for infinite queries, it will only fetch one page if that's what you do, but if there are more pages on the client, they will be overwritten because there is only one cache entry per infinite query
you could switch to using
initialData
, however, what will happen is that the fetch on the server will still happen, it will be sent to the client, but there, it will be discarded.
the whole "revalidation on the server" in nextJs is a bit weird with client cachesgenetic-orangeOP•2y ago
Why do they get re-rendered on server or even the client components when there are no changes happening? I will try the
initialData
today, tell you if it works. Btw the { cache} from "react" doesn't help, it still re-renders the component, to my understanding this makes sense, cache only makes sure not the rerun, so wrapping the entire prefetchInfiniteQuery
doesn't help as in the end the queryClient
does get updated with the hydrated queryClient
overriding everything in the cache.
Do you think I should go back to using pages router instead or app? Won't it solve the issue as there is only one time interaction with the server on build time, and its all on client there after ?yelping-magenta•2y ago
cache is request bound - the next request doesn't know anything from what was cached in a previous request
If you navigate between pages, the server components of that route re-execute on the server. That's how the app directory works (except for shared layouts). getServerSideProps is also called on each navigation, so you'd have the same problem there
genetic-orangeOP•2y ago
Good news, I found this is not an issue in the production build. I did an
npm run build
followed by npm run start
and the whole cache is issue just not there. I imagine the npm run dev
makes alot of re-renders to make sure, we don't run into any weird bugs? The whole re-render of the server component doesn't happen in production ig. I assume this is because, I can see all my pages and static or SSG in the build logs and only server components with SSR needs to re-render on every request?
I think its worth mentioning about this issue somewhere in the docs. Its very confusing.genetic-orangeOP•2y ago
I also want to mention,
https://github.com/vercel/next.js/discussions/54075
search for <Link>, this explains alot
GitHub
Deep Dive: Caching and Revalidating · vercel next.js · Discussion #...
The Next.js App Router introduced new heuristics around caching and revalidating. To ensure we’re all discussing the intended behavior of how caching is designed to work, I thought it would be help...
yelping-magenta•2y ago
The whole re-render of the server component doesn't happen in productionI think there might just be a longer cache in production
I assume this is because, I can see all my pages and static or SSG in the build logsoh okay, yeah SSG is the default in next unless you access cookies() or explicitly opt out
genetic-orangeOP•2y ago
Are there any issues with
<HydrationBoundary>
with app router?. I was having this moment of flicker the first time fetchNext
got called and the UI would just bounce, then I have to click again to make it work. When I replaced it with using queryclient.fetchInfiniteQuery
and initialData
it seems to work perfectly fine. Any explanation ?