Next.js 14 + React Query实现SSR异常:无服务端渲染效果
排查React Query + Next.js App Router SSR失效问题
以下是导致SSR未生效的核心问题及修复方案:
1. QueryClient实例不共享(核心问题)
RootLayout中创建的用于预取/脱水的QueryClient,和客户端Providers里创建的QueryClient是完全独立的实例,服务器预取的状态无法被客户端复用,导致客户端会重新发起请求。
修复方案:
将HydrationBoundary移到QueryClientProvider内部,确保两者使用同一个QueryClient实例;同时在客户端用服务器脱水的状态初始化QueryClient。
修改后的app/layout.tsx:
export default async function RootLayout({children}: {children: React.ReactNode}) { const queryClient = getQueryClient() const dehydratedState = dehydrate(queryClient) return ( <html> <body> <Providers dehydratedState={dehydratedState}> {children} </Providers> </body> </html> ) }
修改后的Providers组件:
'use client' import React, { useState } from 'react' import { QueryClient, QueryClientProvider, HydrationBoundary } from '@tanstack/react-query' function Providers({ children, dehydratedState }: React.PropsWithChildren<{ dehydratedState: any }>) { const [client] = useState( () => { const queryClient = new QueryClient({ defaultOptions: { queries: { staleTime: 60 * 1000 } } }) if (dehydratedState) { queryClient.hydrate(dehydratedState) } return queryClient } ) return ( <QueryClientProvider client={client}> <HydrationBoundary state={dehydratedState}> {children} </HydrationBoundary> </QueryClientProvider> ) } export default Providers
2. 预取InfiniteQuery的配置与客户端Query不匹配
AdminUsersList中预取时,queryFn直接调用fetchUsers(0),没有遵循useInfiniteQuery的参数格式,且缺少getNextPageParam配置,导致预取的数据无法被客户端的useInfiniteQuery正确识别。
修复方案:
预取时完全对齐客户端useInfiniteQuery的配置:
export default async function AdminUsersList() { const queryClient = getQueryClient() await queryClient.prefetchInfiniteQuery({ queryKey: ['users'], queryFn: ({ pageParam }) => fetchUsers(pageParam), initialPageParam: 0, getNextPageParam: (lastPage) => lastPage.nextCursor, }) return ( <UserList /> ) }
3. HydrationBoundary位置错误
原代码中HydrationBoundary在QueryClientProvider外部,无法访问客户端的QueryClient实例,无法完成状态复现。修复后已将其移动到QueryClientProvider内部(见Providers组件修改)。
验证SSR是否生效
修复后查看页面HTML源码,如果能直接看到用户列表内容(而非loading...),说明SSR已生效。
内容的提问来源于stack exchange,提问作者Free
相关产品推荐
相关产品推荐

