SuperAPI AI 工具集

tanstack-query-intent-lifecycle-ssr-hydration-and-streaming

前端与建站

查看项目

更新于 10-16 08:19

技能介绍

用途

该技能用于指导在服务端渲染(SSR)场景下正确使用 TanStack Query,涉及意图、生命周期、dehydrate、hydrate、HydrationBoundary,以及 TanStack Start、TanStack Router 的 SSR Query 集成、Next.js App Router 与 Next.js Pages Router 等框架。目标是让服务端预取的数据能够正确注水(hydrate)到客户端缓存,避免重复请求与数据不同步。

主要能力

  • 使用 dehydrate 与 HydrationBoundary 将服务端预取的数据传递到客户端。
  • 通过 prefetchQuery 在服务端预取数据,再由 HydrationBoundary 注水。
  • 在 TanStack Start 与 TanStack Router 中通过 setupRouterSsrQueryIntegration 集成 SSR Query。
  • 为每个请求创建独立的 QueryClient(per-request clients)。
  • 仅注水已预取的数据。
  • 识别并规避常见错误,例如 RSC 中重复渲染已获取数据、Suspense 查询未在服务端预取、SvelteKit 查询在 SSR 响应后执行等。

使用方式

基础设置示例:

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

export async function PostsPage() {
  const queryClient = new QueryClient()
  await queryClient.prefetchQuery({
    queryKey: ['posts'],
    queryFn: async () => [{ id: 1 }],
  })
  return (
    <HydrationBoundary state={dehydrate(queryClient)}>
      <main>Posts</main>
    </HydrationBoundary>
  )
}

TanStack Start 与 Router 优先集成:

import { QueryClient } from '@tanstack/react-query'
import { createRouter } from '@tanstack/react-router'
import { setupRouterSsrQueryIntegration } from '@tanstack/react-router-ssr-query'
import { routeTree } from './routeTree.gen'

const queryClient = new QueryClient()
const router = createRouter({ routeTree, context: { queryClient } })

setupRouterSsrQueryIntegration({ router, queryClient })

按请求创建客户端:

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

export function createSsrQueryClient() {
  return new QueryClient({
    defaultOptions: { queries: { staleTime: 60_000 } },
  })
}

仅注水已预取数据:

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

export async function Page() {
  const queryClient = new QueryClient()
  await queryClient.prefetchQuery({
    queryKey: ['profile'],
    queryFn: async () => ({ name: 'Tanner' }),
  })
  return (
    <HydrationBoundary state={dehydrate(queryClient)}>
      <main>Profile</main>
    </HydrationBoundary>
  )
}

常见错误

严重:RSC 重复渲染已获取数据

错误写法:

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

export async function Page() {
  const queryClient = new QueryClient()
  const posts = await queryClient.fetchQuery({
    queryKey: ['posts'],
    queryFn: async () => [{ id: 1 }],
  })
  return (
    <>
      <p>{posts.length}</p>
      <HydrationBoundary state={dehydrate(queryClient)}>
        <main>Posts</main>
      </HydrationBoundary>
    </>
  )
}

正确写法:

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

export async function Page() {
  const queryClient = new QueryClient()
  await queryClient.prefetchQuery({
    queryKey: ['posts'],
    queryFn: async () => [{ id: 1 }],
  })
  return (
    <HydrationBoundary state={dehydrate(queryClient)}>
      <main>Posts</main>
    </HydrationBoundary>
  )
}

服务端渲染的派生数据可能与客户端重新获取的 Query 数据不同步。

来源:TanStack/query:docs/framework/react/guides/advanced-ssr.md

严重:Suspense 查询未在服务端预取

错误写法:

import { useSuspenseQuery } from '@tanstack/react-query'

export function Posts() {
  const { data } = useSuspenseQuery({
    queryKey: ['posts'],
    queryFn: async () => [{ id: 1 }],
  })
  return <pre>{JSON.stringify(data)}</pre>
}

正确写法:

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

export async function Page() {
  const queryClient = new QueryClient()
  await queryClient.prefetchQuery({
    queryKey: ['posts'],
    queryFn: async () => [{ id: 1 }],
  })
  return (
    <HydrationBoundary state={dehydrate(queryClient)}>
      <main>Posts</main>
    </HydrationBoundary>
  )
}

未预取的 Suspense 查询可能在服务端发起请求、注水失败,然后在客户端再次请求。

来源:TanStack/query:docs/framework/react/guides/ssr.md

高:SvelteKit 查询在 SSR 响应后执行

错误写法:

import { QueryClient } from '@tanstack/svelte-query'

export const queryClient = new QueryClient()

正确写法:

import { browser } from '$app/environment'
import { QueryClient } from '@tanstack/svelte-query'

export const queryClient = new QueryClient({
  defaultOptions: { queries: { enabled: browser } },
})

除非显式预取服务端数据,SvelteKit SSR 需要通过 browser 门控默认查询执行。

来源:TanStack/query:docs/framework/svelte/ssr.md

另见:compositions/compose-query-with-tanstack-router-and-start,用于 TanStack 自有的 SSR 路由。

适用场景

  • 使用 Next.js App Router 或 Pages Router 并需要服务端预取数据。
  • 使用 TanStack Start 或 TanStack Router 并需要 SSR Query 集成。
  • 使用 SvelteKit 并需要控制查询在服务端与客户端的执行时机。
  • 需要在服务端预取数据后通过 HydrationBoundary 注水到客户端缓存。

限制

资料未提供该技能的具体安装命令、收费方式、价格、平台支持范围或效果数据,这些信息暂未提供。