用途
本技能介绍 TanStack Router 中搜索参数(Search Params)的处理方式。TanStack Router 将搜索参数视为 JSON 优先的应用状态:它们会从 URL 自动解析为结构化对象(数字、布尔值、数组、嵌套对象),并在每个路由上通过 validateSearch 进行校验。
主要能力
- 通过 validateSearch 对每个路由的搜索参数进行校验。
- 支持 Zod、Valibot、ArkType 适配器。
- 类型完全推断,无需手动标注 useSearch() 的返回值。
- 支持搜索参数继承:父路由的搜索参数会自动合并到子路由。
- 提供搜索中间件:retainSearchParams(跨导航保留参数)、stripSearchParams(从 URL 中移除默认值),并支持链式组合。
- 支持在路由器级别自定义序列化(parseSearchWith / stringifySearchWith)。
- 支持通过 loaderDeps 在 loader 中使用搜索参数。
使用方式
安装(Zod 适配器,推荐)
npm install zod @tanstack/zod-adapter
定义校验
// src/routes/products.tsx
import { createFileRoute } from '@tanstack/react-router'
import { z } from 'zod'
const productSearchSchema = z.object({
page: z.number().default(1).catch(1),
filter: z.string().default(''),
sort: z.enum(['newest', 'oldest', 'price']).default('newest').catch('newest'),
})
export const Route = createFileRoute('/products')({
validateSearch: productSearchSchema,
component: ProductsPage,
})
读取搜索参数
- 路由组件内:
Route.useSearch() - 代码分割组件内:
getRouteApi('/products')后调用routeApi.useSearch() - 任意组件:
useSearch({ from: '/products' }) - 宽松访问:
useSearch({ strict: false })
写入搜索参数
- Link 函数形式(保留现有参数):
search={(prev) => ({ ...prev, page: prev.page + 1 })} - Link 对象形式(替换全部参数):
search={{ page: 1, filter: '', sort: 'newest' }} - 编程式:
useNavigate()配合navigate({ search: (prev) => ({ ...prev, sort: e.target.value, page: 1 }) })
搜索中间件
- retainSearchParams:
middlewares: [retainSearchParams(['debug'])] - stripSearchParams:
middlewares: [stripSearchParams(defaults)] - 可链式组合多个中间件。
自定义序列化
import { createRouter, parseSearchWith, stringifySearchWith } from '@tanstack/react-router'
const router = createRouter({
routeTree,
parseSearch: parseSearchWith(parse),
stringifySearch: stringifySearchWith(stringify),
})
在 loader 中使用(loaderDeps)
export const Route = createFileRoute('/products')({
validateSearch: productSearchSchema,
loaderDeps: ({ search }) => ({ page: search.page }),
loader: async ({ deps }) => {
return fetchProducts({ page: deps.page })
},
})
适用场景
适用于使用 TanStack Router 构建的 React 应用,需要在 URL 中保存和同步筛选、排序、分页等状态,并希望获得类型安全的校验与读写体验的场景。
限制与注意事项
- 使用 zodValidator() 且为 Zod v3 时,应使用 @tanstack/zod-adapter 的 fallback(),而非 zod 的 .catch();使用 .catch() 会使输出类型变为 unknown,破坏类型安全。此限制不适用于 Valibot 或 ArkType(它们使用各自的 fallback 机制),也不适用于 Zod v4(v4 应使用 .catch(),且不使用 zodValidator())。
- 类型完全推断,切勿标注 useSearch() 的返回值。
- loaderDeps 不应返回整个 search 对象,否则任何搜索参数变化都会导致 loader 重新运行;应只挑选 loader 需要的参数。
- 不要在搜索参数中传递 Date 对象,应转换为 ISO 字符串。
- 父路由缺少 validateSearch 会阻止子路由继承共享参数。
- 使用对象形式的 search 会替换全部搜索参数,若需保留现有参数应使用函数形式。