Next.js 15 RC to 15 Stable update breaks hydration with React-Query
Unanswered
Standard Chinchilla posted this in #help-forum
Standard ChinchillaOP
My project worked flawlessly under Next.js 15 RC0, but updating to 15 stable seems to cause errors and break hydration with React-Query prefetching. I am using the App router.
This is my page server component.
I get this error:
And hydration is consequently broken for the page.
It only disappears when I remove the HydrationBoundary which injects the queryClient. Of course hydration won't work properly without react-query prefetching so that's not an option.
This is what prefetchSearchPage looks like:
export default async function SearchPage({
searchParams,
}: {
searchParams: { [key: string]: string | string[] | undefined };
}) {
const queryClient = new QueryClient()
const request = await prefetchSearchPage(queryClient, searchParams)
const restrictedMode = process.env.RESTRICTED_MODE === "true"
return (
<HydrationBoundary state={dehydrate(queryClient)}>
<SearchPageContent
isRestrictedMode={restrictedMode}
/>
</HydrationBoundary>
)
}
This is my page server component.
I get this error:
Only plain objects can be passed to Client Components from Server Components. Objects with symbol properties like async_id_symbol are not supported.
{query: {}}
^^
And hydration is consequently broken for the page.
It only disappears when I remove the HydrationBoundary which injects the queryClient. Of course hydration won't work properly without react-query prefetching so that's not an option.
This is what prefetchSearchPage looks like:
export const prefetchSearchPage = async (
queryClient: QueryClient,
searchParams: {
[key: string]: string | string[] | undefined
}
): Promise<SearchQueryArgs> => {
const searchQuery = getSearchQueryCache(searchParams)
const dbs = selectedDBsServer.parse(searchParams)
const partitionBy = partitionByParamsCache.parse(searchParams)
const searchRequest = {
params: {
query: dbs,
},
body: {
...searchQuery,
results: true,
count: false,
partition_by: partitionBy.partition_by as any,
},
}
await queryClient.prefetchQuery({
queryKey: ["post", "/api/search/pql", searchRequest],
queryFn: () => JSON.parse(JSON.stringify(fetchSearch(searchRequest))),
})
}
2 Replies
Standard ChinchillaOP
"@tanstack/react-query": "^5.59.20",
"@tanstack/react-query-devtools": "^5.59.20",
"babel-plugin-react-compiler": "^19.0.0-beta-63b359f-20241101",
"react": "^19.0.0-rc-5c56b873-20241107",
"react-dom": "^19.0.0-rc-5c56b873-20241107",
"next": "^15.0.3",
"nuqs": "^1.19.3",
"openapi-fetch": "^0.13.0",
"openapi-react-query": "^0.2.4",
Standard ChinchillaOP
Ok. I solved the issue myself. In the end, it turns out all the problems were being caused by the new asynchronous searchParams API. I read in the docs that sync access still worked, but it seems like it was giving me promises by default anyways.