Next.js服务端组件中如何使用React Query(TANStack)?兼解SSR/SSG困惑
React Query 与 Next.js SSR/SSG 的互补关系
1. SSR/SSG 的核心价值并未失效
SSR(服务端渲染)和 SSG(静态站点生成)的核心是在服务端提前生成页面完整 HTML,这两个核心优势依然不可替代:
- 更优的 SEO:搜索引擎能直接抓取到渲染完成的页面内容,无需依赖客户端 JS 执行后生成的内容。
- 更快的首屏体验:用户打开页面时能立刻看到内容,不用等待客户端 JS 加载、解析完成才显示。
React Query 的 useQuery 确实是客户端钩子,但这并不意味着要放弃 SSR/SSG,二者完全可以配合使用,发挥各自的优势。
2. React Query 与 SSR/SSG 的配合方案
方案一:服务端预取数据,客户端用 React Query 接管缓存
在 Next.js 中,你可以通过 getServerSideProps(SSR)或 getStaticProps(SSG)在服务端获取数据,将数据作为 props 传给页面组件。之后在客户端组件中,用 useQuery 的 initialData 选项把服务端预取的数据作为初始缓存,后续的数据更新、重新获取等逻辑交给 React Query 处理:
// 页面组件(支持 SSR/SSG) export async function getServerSideProps() { const initialData = await fetch('https://api.example.com/posts').then(res => res.json()); return { props: { initialData } }; } export default function PostsPage({ initialData }) { const { data } = useQuery({ queryKey: ['posts'], queryFn: () => fetch('https://api.example.com/posts').then(res => res.json()), initialData: initialData, }); return ( <div> {data?.map(post => <div key={post.id}>{post.title}</div>)} </div> ); }
这种方式既保留了 SSR/SSG 的首屏加载优势,又能利用 React Query 的缓存、自动重试、背景刷新等特性优化客户端数据交互。
方案二:React Query 官方 SSR 适配工具
React Query 提供了 dehydrate 和 hydrate 工具,专门用于服务端渲染场景:
- 服务端:创建
QueryClient实例,用prefetchQuery预取数据,再通过dehydrate将缓存序列化为 JSON。 - 客户端:用
hydrate把服务端传递的缓存数据恢复到客户端的QueryClient中,这样useQuery就能直接读取缓存,无需重复请求。
示例代码:
// 服务端逻辑(getServerSideProps/getStaticProps) import { QueryClient, dehydrate } from '@tanstack/react-query'; export async function getStaticProps() { const queryClient = new QueryClient(); await queryClient.prefetchQuery({ queryKey: ['posts'], queryFn: () => fetch('https://api.example.com/posts').then(res => res.json()), }); return { props: { dehydratedState: dehydrate(queryClient), }, }; } // 客户端页面组件 import { QueryClient, QueryClientProvider, hydrate } from '@tanstack/react-query'; import PostsClientComponent from './PostsClientComponent'; export default function PostsPage({ dehydratedState }) { const queryClient = new QueryClient(); hydrate(queryClient, dehydratedState); return ( <QueryClientProvider client={queryClient}> <PostsClientComponent /> </QueryClientProvider> ); } // 客户端组件 function PostsClientComponent() { const { data } = useQuery({ queryKey: ['posts'], queryFn: () => fetch('https://api.example.com/posts').then(res => res.json()), }); return ( <div> {data?.map(post => <div key={post.id}>{post.title}</div>)} </div> ); }
3. React Query 解决 SSR/SSG 覆盖不到的场景
SSR/SSG 更适合静态或准静态的页面内容,但以下场景中,React Query 的价值会凸显:
- 动态内容实时更新:比如用户点赞、评论后,React Query 可以自动重新获取数据,无需刷新整个页面。
- 用户专属数据:个人信息、购物车这类和当前用户绑定的数据,无法在服务端提前预取,必须在客户端获取,React Query 的缓存、重试机制能让这个过程更高效。
- 背景数据刷新:用户浏览页面时,React Query 可以在后台悄悄更新数据,用户切换回来时就能看到最新内容,无需手动刷新。
总结
SSR/SSG 负责解决首屏加载速度和 SEO 问题,React Query 负责优化客户端数据管理的效率,二者是互补关系,而非二选一。合理结合使用,既能让页面加载快、搜索引擎友好,又能让客户端的数据交互更流畅。
内容的提问来源于stack exchange,提问作者Yaseen Jabir
相关产品推荐
相关产品推荐

