执行契约
- 适用场景
- Loader、beforeLoad 和路由组件需要共享 QueryClient、认证读取器或其他应用级依赖。
- 不要使用
- 不要把频繁变化的页面状态或只属于单个组件的数据塞入 Router Context。
- 前置检查
- 通过注册类型定义最小接口,并确定依赖在 RouterProvider 外部如何取得。
- 验证结果
- 缺少必需依赖时编译失败,父级 beforeLoad 扩展的 Context 在子路由中保持准确类型。
- 失败模式
- Context 变成 any 通常来自缺少模块注册或在创建 Router 时做了强制断言。
- 安全边界
- Context 可帮助传递鉴权能力,但不能把客户端认证状态视为服务端授权证据。
根契约
使用 createRootRouteWithContext<RouterContext>() 声明根依赖。createRouter.context 必须满足该类型;不要用非空断言掩盖真正缺失的服务。
import { createRootRouteWithContext } from '@tanstack/react-router'
import type { QueryClient } from '@tanstack/react-query'
type RouterContext = { queryClient: QueryClient }
export const Route = createRootRouteWithContext<RouterContext>()({
component: RootDocument,
})子树扩展
beforeLoad 可以同步或异步返回新 context,返回值会与父级 context 合并并传给子路由。只返回子树真正需要的稳定事实,避免每个 loader 重复计算。
权限边界
beforeLoad 可以阻止导航或重定向,但客户端路由状态可以被绕过。服务端数据入口必须独立验证身份与权限,不能把 canEdit 这类 context 布尔值当作授权证明。