You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Next.js中使用React Query实现服务端渲染?

在Next.js中用React Query实现服务端渲染的解决方案

因为React Query的hooks依赖客户端环境,服务端组件无法直接使用,下面是几种可行的实现方案:

方案1:服务端预取数据 + React Query 脱水/注水(App Router)

在服务端组件中预取数据,通过dehydrate将QueryClient中的数据序列化,再传给客户端组件用Hydrate注入,让React Query复用服务端数据,避免重复请求。

代码示例

服务端组件(page.tsx):

import { dehydrate, QueryClient } from '@tanstack/react-query'
import TodoClientComponent from './TodoClientComponent'

export default async function TodoPage() {
  const queryClient = new QueryClient()

  // 服务端预取数据,queryKey需和客户端useQuery保持一致
  await queryClient.prefetchQuery({
    queryKey: ['todos'],
    queryFn: () => fetch('https://api.example.com/todos').then(res => res.json()),
  })

  const dehydratedState = dehydrate(queryClient)

  return <TodoClientComponent dehydratedState={dehydratedState} />
}

客户端组件(TodoClientComponent.tsx,需添加'use client'指令):

'use client'

import { Hydrate, QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { useQuery } from '@tanstack/react-query'

export default function TodoClientComponent({ dehydratedState }: { dehydratedState: any }) {
  const queryClient = new QueryClient()

  return (
    <QueryClientProvider client={queryClient}>
      <Hydrate state={dehydratedState}>
        <TodoList />
      </Hydrate>
    </QueryClientProvider>
  )
}

function TodoList() {
  // 自动复用服务端预取的数据,无需重复请求
  const { data } = useQuery({
    queryKey: ['todos'],
    queryFn: () => fetch('https://api.example.com/todos').then(res => res.json()),
  })

  return (
    <ul>
      {data?.map(todo => <li key={todo.id}>{todo.title}</li>)}
    </ul>
  )
}

方案2:服务端组件传初始数据给客户端组件

在服务端组件直接获取数据,将数据作为props传给客户端组件,客户端用useQuery的initialData参数使用该数据,同时保留React Query的缓存能力。

代码示例

服务端组件(page.tsx):

import TodoClientComponent from './TodoClientComponent'

export default async function TodoPage() {
  const todos = await fetch('https://api.example.com/todos').then(res => res.json())
  return <TodoClientComponent initialTodos={todos} />
}

客户端组件(TodoClientComponent.tsx):

'use client'

import { QueryClient, QueryClientProvider, useQuery } from '@tanstack/react-query'

export default function TodoClientComponent({ initialTodos }: { initialTodos: any[] }) {
  const queryClient = new QueryClient()

  return (
    <QueryClientProvider client={queryClient}>
      <TodoList initialTodos={initialTodos} />
    </QueryClientProvider>
  )
}

function TodoList({ initialTodos }: { initialTodos: any[] }) {
  const { data } = useQuery({
    queryKey: ['todos'],
    queryFn: () => fetch('https://api.example.com/todos').then(res => res.json()),
    initialData: initialTodos, // 直接使用服务端传来的初始数据
  })

  return (
    <ul>
      {data?.map(todo => <li key={todo.id}>{todo.title}</li>)}
    </ul>
  )
}

方案3:Page Router 下的实现(Next.js 12及更早)

若使用Page Router,可通过getServerSideProps预取数据并脱水,再传给页面组件:

// pages/todos.tsx
import { dehydrate, Hydrate, QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { useQuery } from '@tanstack/react-query'

export async function getServerSideProps() {
  const queryClient = new QueryClient()

  await queryClient.prefetchQuery({
    queryKey: ['todos'],
    queryFn: () => fetch('https://api.example.com/todos').then(res => res.json()),
  })

  return {
    props: {
      dehydratedState: dehydrate(queryClient),
    },
  }
}

export default function TodosPage({ dehydratedState }) {
  const queryClient = new QueryClient()

  return (
    <QueryClientProvider client={queryClient}>
      <Hydrate state={dehydratedState}>
        <TodoList />
      </Hydrate>
    </QueryClientProvider>
  )
}

function TodoList() {
  const { data } = useQuery({
    queryKey: ['todos'],
    queryFn: () => fetch('https://api.example.com/todos').then(res => res.json()),
  })

  return (
    <ul>
      {data?.map(todo => <li key={todo.id}>{todo.title}</li>)}
    </ul>
  )
}

注意事项

  • 服务端组件不能直接使用useQuery等React Query hooks,必须在客户端组件中调用。
  • 脱水/注水方案能完整保留React Query的缓存、自动重新获取等特性,适合复杂场景;传初始数据的方式更简单,适合基础场景。
  • 确保服务端和客户端的queryKey完全一致,否则React Query无法匹配缓存数据。

内容的提问来源于stack exchange,提问作者arjun tv

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 04:42:35