---
id: route-context
track: learn
product: router
locale: zh-CN
order: 9
revision: 2
sourceCheckedOn: "2026-08-03"
versionRange: "Router ^1"
verifiedAgainst: "@tanstack/react-router@1.170.18"
contentModel: 2
prerequisites:
  - "理解根路由与嵌套路由"
  - "理解 TypeScript 接口"
sourceRefs:
  - "https://tanstack.com/router/latest/docs/guide/router-context"
  - "https://tanstack.com/router/latest/docs/framework/react/guide/authenticated-routes"
---

# 用 Router Context 传递依赖

> 在根路由声明类型化依赖，再通过 beforeLoad 为一棵子路由追加经过推导的上下文。

**Outcome:** 能为 QueryClient、会话或服务定义类型化 Router Context，并理解它与服务端授权的边界。

## 根路由声明最小契约

createRootRouteWithContext 让路由树要求 createRouter 提供相同依赖。把跨 loader、beforeLoad 和路由组件共享的稳定依赖放在这里，不要把任意组件状态都塞进全局 context。

File: `src/routes/__root.tsx`

```tsx
import { createRootRouteWithContext } from '@tanstack/react-router'
import type { QueryClient } from '@tanstack/react-query'

type RouterContext = {
  queryClient: QueryClient
  session: { permissions: readonly string[] }
}

export const Route = createRootRouteWithContext<RouterContext>()({
  component: RootDocument,
})
```

## 让父路由追加派生事实

beforeLoad 的返回值会合并进该路由及其子路由的 context。父级只计算一次 canEditIssues，子 loader 不必重复解释权限字符串，也能得到完整类型推断。

> **Note:** 客户端 beforeLoad 改善导航体验，但不是数据授权边界；Server Function 或 Server Route 仍必须重新授权。

File: `src/routes/_workspace.tsx`

```tsx
import { createFileRoute } from '@tanstack/react-router'

export const Route = createFileRoute('/_workspace')({
  beforeLoad: ({ context }) => ({
    canEditIssues: context.session.permissions.includes('issues:write'),
  }),
})
```

## 实践与验证

### 完成检查点

Router Context 的依赖在创建 Router 时注入，并在 beforeLoad 与 Loader 中保持类型安全。

### 动手练习

把 QueryClient 和一个 auth 读取接口加入根 Context，在受保护路由中消费它们。

### 验证方法

删除一个必需依赖时 Router 创建应产生类型错误；恢复后 Loader 能读到同一实例。

### 常见错误

- 在路由模块顶层调用 React Hook。
- 用 any 绕过 Router Context 的注册类型。

## Official sources

- https://tanstack.com/router/latest/docs/guide/router-context
- https://tanstack.com/router/latest/docs/framework/react/guide/authenticated-routes
