---
id: query.loader-prefetch
kind: recipe
product: query
framework: react
locale: zh-CN
revision: 2
sourceCheckedOn: "2026-08-03"
versionRange: "Query ^5 / Router ^1"
verifiedAgainst: "@tanstack/react-query@5.101.4 + @tanstack/react-router@1.170.18 + @tanstack/react-router-ssr-query@1.167.1"
contentModel: 2
packages:
  - "@tanstack/react-query"
  - "@tanstack/react-router"
  - "@tanstack/react-router-ssr-query"
tasks:
  - "prefetch-query-in-loader"
  - "ssr-hydration"
  - "avoid-request-waterfall"
sourceRefs:
  - "https://tanstack.com/router/latest/docs/integrations/query"
---

# 在路由 Loader 中预取 Query

> 为 SSR 创建请求级 QueryClient，并让 Loader 与 useSuspenseQuery 使用相同 queryOptions。

## 执行契约

- **适用场景:** 目标路由进入前应预热 Query 缓存，并由组件继续观察同一数据。
- **不要使用:** 首屏不需要、用户很少访问或成本很高的数据不应无条件阻塞 Loader。
- **前置检查:** 建立共享 queryOptions 工厂，并确保 Loader deps 包含影响 Query Key 的所有路由输入。
- **验证结果:** 导航期间只触发一个网络请求，组件命中相同缓存；变更参数时产生不同且可预测的 Key。
- **失败模式:** 若组件立即重复请求，比较 Loader 与组件的完整 Query Key、新鲜度和 QueryClient 实例。
- **安全边界:** 预取不会隐藏响应；不要将未经授权的数据放入可序列化缓存或 SSR 负载。

## 前置集成

在 getRouter 内创建 QueryClient，将它放入 Router context，然后调用 setupRouterSsrQueryIntegration。getRouter 在 SSR 中按请求执行；不要把 QueryClient 提升到模块级单例。

File: `src/router.tsx`

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

setupRouterSsrQueryIntegration({ router, queryClient })
```

## 阻塞式关键数据

对渲染必需的数据，从 Loader 返回 ensureQueryData Promise。组件用相同 queryOptions 调用 useSuspenseQuery。这样 Router 等待导航，Query 管理缓存，SSR 集成完成脱水与恢复。

File: `src/routes/issues/index.tsx`

```tsx
const issuesQuery = queryOptions({
  queryKey: ['issues'],
  queryFn: getIssues,
})

export const Route = createFileRoute('/issues/')({
  loader: ({ context }) =>
    context.queryClient.ensureQueryData(issuesQuery),
  component: () => {
    const { data } = useSuspenseQuery(issuesQuery)
    return <IssueList issues={data} />
  },
})
```

## 验证清单

确认 Router 根 context 声明了 QueryClient 类型；确认服务端没有跨请求共享 QueryClient；确认 Loader 与组件的 queryKey 完全一致；运行 SSR 页面并检查客户端未重复首屏请求。

## Official sources

- https://tanstack.com/router/latest/docs/integrations/query
