Next.js Discord

Discord Forum

Next.js 15 RC to 15 Stable update breaks hydration with React-Query

Unanswered
Standard Chinchilla posted this in #help-forum
Open in Discord
Avatar
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.


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

Avatar
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",
Avatar
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.