You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In our NextJS application (app router) we're prefetching the logged in user on all requests via prefetchQuery + HydrationBoundary in the global layout. Currently this opts us into dynamic rendering across the board and so I'm reworking this to be optional on a per-page basis.
We use the logged in user in our application header as well as for various page-specific tasks (e.g. determining whether to show sign up CTAs).
My plan was to move the prefetching into each individual page in our application via a higher order component. Then we can selectively remove that HOC on pages where we want to adopt static rendering. After doing this however I was seeing loading indicators show up across the board on first page load despite being able to debug that the prefetch logic is executing as expected before the initial response returns.
I believe I've tracked the issue down to using the prefetched query in a layout component higher in the tree than the page component which is doing the prefetching. When doing this both the layout consumer and page consumer cannot access the prefetched data on first render. It's understandable that the layout consumer doesn't have the data but I'd expect the page consumer to have access to it and render with that data immediately.
At http://localhost:3000 you can access dev tools then look at the HTML response for the page to see it returns with the prefetched data as expected (see screenshot). This page doesn't try to consume the query in its layout, only in the page.
At http://localhost:3000/broken you can look at the HTML response to see both the layout and page components render without the prefetched data (see screenshot). I've put in an artificial delay on the query and you can observe that the response does indeed wait on this. Instead of rendering with the data a loading state is shown for both consumers.
After loading /broken, some kind of hydration immediately swaps out the loading state for the correct value which suggests RQ does indeed have access to it and the data is crossing the client-server boundary. If RQ didn't have access to the data then the loading state would be shown for 5 seconds before the query resolves due to the artificial delay.
Expected behavior
I would expect the page to render with the prefetched data immediately and the layout to render in a loading state since the query is prefetched after the layout renders.
I think this behaviour occurs because PrefetchIt is not wrapped in a suspense boundary, thus the “global” suspense boundary from next kicks in, which also wraps the layout.
wrapping either the children of the Home component in Suspense:
Describe the bug
In our NextJS application (app router) we're prefetching the logged in user on all requests via prefetchQuery + HydrationBoundary in the global layout. Currently this opts us into dynamic rendering across the board and so I'm reworking this to be optional on a per-page basis.
We use the logged in user in our application header as well as for various page-specific tasks (e.g. determining whether to show sign up CTAs).
My plan was to move the prefetching into each individual page in our application via a higher order component. Then we can selectively remove that HOC on pages where we want to adopt static rendering. After doing this however I was seeing loading indicators show up across the board on first page load despite being able to debug that the prefetch logic is executing as expected before the initial response returns.
I believe I've tracked the issue down to using the prefetched query in a layout component higher in the tree than the page component which is doing the prefetching. When doing this both the layout consumer and page consumer cannot access the prefetched data on first render. It's understandable that the layout consumer doesn't have the data but I'd expect the page consumer to have access to it and render with that data immediately.
Your minimal, reproducible example
https://github.com/cbovis/rq-hydration-issue
Steps to reproduce
I've setup a simple NextJS application which demonstrates the issue in the simplest way possible.
pnpm install
all the dependenciespnpm dev
to start up dev serverAt http://localhost:3000 you can access dev tools then look at the HTML response for the page to see it returns with the prefetched data as expected (see screenshot). This page doesn't try to consume the query in its layout, only in the page.
At http://localhost:3000/broken you can look at the HTML response to see both the layout and page components render without the prefetched data (see screenshot). I've put in an artificial delay on the query and you can observe that the response does indeed wait on this. Instead of rendering with the data a loading state is shown for both consumers.
After loading
/broken
, some kind of hydration immediately swaps out the loading state for the correct value which suggests RQ does indeed have access to it and the data is crossing the client-server boundary. If RQ didn't have access to the data then the loading state would be shown for 5 seconds before the query resolves due to the artificial delay.Expected behavior
I would expect the page to render with the prefetched data immediately and the layout to render in a loading state since the query is prefetched after the layout renders.
How often does this bug happen?
Every time
Screenshots or Videos
Platform
In the reproduction repo:
"@tanstack/react-query": "^5.62.11"
"next": "15.1.3",
"prettier": "^3.4.2",
"react": "^19.0.0",
"react-dom": "^19.0.0"
Also occurring in our application which uses:
React 18
NextJS 14
React Query 5
Tanstack Query adapter
react-query
TanStack Query version
5.62.11
TypeScript version
No response
Additional context
No response
The text was updated successfully, but these errors were encountered: