开发工具与调试
TanStack Router 提供了专用的 Devtools 面板和多种调试手段,帮助可视化路由状态、追踪导航流程、排查路由问题。
安装 Devtools
npm install -D @tanstack/react-router-devtools
# 或
npm install -D @tanstack/router-devtools基础使用
// src/App.tsx
import { TanStackRouterDevtools } from '@tanstack/react-router-devtools'
import { RouterProvider } from '@tanstack/react-router'
import { router } from './router'
function App() {
return (
<>
<RouterProvider router={router} />
{/* 仅在开发环境显示 */}
<TanStackRouterDevtools router={router} />
</>
)
}💡 最佳实践:Devtools 默认只在
development模式下显示。生产环境可以用条件包裹:{import.meta.env.DEV && <TanStackRouterDevtools router={router} />}
Devtools 面板位置
// 调整面板位置(默认在右下角)
<TanStackRouterDevtools
router={router}
position="bottom-left" // 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right'
/>
// 自定义面板样式
<TanStackRouterDevtools
router={router}
panelStyle={{ height: '600px' }}
/>Devtools 功能
路由树可视化
Devtools 展示完整的路由树结构,包括:
- 每个路由的路径、状态(active / inactive)
- Loader 状态(pending / loaded / error)
- 路径无关布局的层级关系
- 当前匹配的路由高亮
路由匹配信息
点击任意路由可查看详细信息:
- 当前参数:path params 和 search params 的实际值
- Loader 数据:缓存的 loader 返回值
- Context:路由上下文内容
- 匹配状态:为什么匹配成功/失败
导航历史
显示最近的导航记录:
- 从哪个路由 → 到哪个路由
- 导航触发原因(用户点击 / 代码调用 / 浏览器前进后退)
- 每次导航的耗时
缓存状态
查看 SWR 缓存信息:
- 哪些路由的 loader 数据在缓存中
- 缓存的 staleTime 和剩余时间
- 手动清除缓存
生产环境使用 Devtools
TanStack Router Devtools 在默认情况下生产环境不渲染任何 UI,但你可以强制显示(例如用于 staging 调试):
<TanStackRouterDevtools
router={router}
initialIsOpen={false} // 初始不展开面板
/>🚨 陷阱:不要将 devtools 面板在生产环境对普通用户开放——它会暴露路由结构、loader 数据等内部信息。如确需在 staging 使用,确保只有内部人员可访问。
调试常见路由问题
1. 路由不匹配
如果页面显示 404 而非预期内容:
- 打开 Devtools → 查看路由树是否包含该路由
- 检查
routeTree.gen.ts是否正确生成(删除后重新npm run dev) - 确认文件命名是否符合约定(
$param、_layout等)
常见错误:
routes/user/$id.tsx ❌ 应为 routes/users/$userId.tsx
routes/posts/new.tsx ✅ 但如果 $postId 也在 posts/ 下会冲突2. 搜索参数类型错误
// 调试 validateSearch
export const Route = createFileRoute('/test')({
validateSearch: (search) => {
console.log('原始 search 参数:', search) // 👈 调试入口
return { page: Number(search.page) || 1 }
},
})3. Loader 不执行或执行异常
export const Route = createFileRoute('/posts/')({
loader: async ({ params, deps, cause, preload }) => {
console.log('Loader 触发:', { params, deps, cause, preload })
// cause: 'enter' (首次进入) | 'stay' (staleTime 内重新进入)
// preload: true/false
return fetchPosts(deps.page)
},
})4. 使用 Devtools 的 “Test” 功能
Devtools 面板提供内置的路由测试功能:
- 手动输入路径查看哪个路由会匹配
- 模拟搜索参数验证结果
- 测试 beforeLoad 守卫逻辑
编程式调试
获取当前路由状态
import { useRouterState } from '@tanstack/react-router'
function DebugPanel() {
const state = useRouterState()
return (
<details>
<summary>Router State</summary>
<pre>{JSON.stringify({
location: state.location,
matches: state.matches.map((m) => m.routeId),
status: state.status,
}, null, 2)}</pre>
</details>
)
}监听路由事件
import { useRouter } from '@tanstack/react-router'
function App() {
const router = useRouter()
useEffect(() => {
const unsubscribe = router.subscribe('onBeforeNavigate', ({ toLocation }) => {
console.log('即将导航到:', toLocation.href)
})
return unsubscribe
}, [router])
}💡 最佳实践:路由事件监听适合做页面加载进度条(NProgress 风格),在
onBeforeNavigate开始、onResolved结束。
类型调试
如果类型推断不符合预期:
// 检查 Route 的类型
import type { Route } from '@tanstack/react-router'
// 利用 TypeScript 的类型提示
const _typeCheck: typeof Route.types.loaderData = {} as any
// 悬停在 _typeCheck 上即可看到 loader 的完整返回类型
常见调试流程
| 问题 | 首要检查 | 工具 |
|---|---|---|
| 页面 404 | 路由树是否包含该路由 | Devtools → Route Tree |
| Loader 数据不对 | loader 参数和返回值 | console.log + Devtools → Loader Data |
| 导航不跳转 | beforeLoad 是否抛出了 redirect | Devtools → Navigation History |
| 搜索参数丢失 | 是否用了函数式更新器 | Devtools → Search Params |
| 类型报错 | 是否执行了 declare module Register |
检查 router.tsx 类型注册 |
| 路由树未更新 | routeTree.gen.ts 是否过期 |
删除后重启 dev server |
Vite 插件调试
// vite.config.ts
import { tanstackRouter } from '@tanstack/router-plugin/vite'
export default defineConfig({
plugins: [
tanstackRouter({
// 输出路由生成日志
logs: true,
// 自定义路由树输出路径
routesDirectory: './src/routes',
generatedRouteTree: './src/routeTree.gen.ts',
}),
react(),
],
})💡 最佳实践:如果路由修改后热更新不生效,可能因为
routeTree.gen.ts缓存。手动删除该文件并重启 dev server。