本技能介绍 TanStack Router 的“未找到”与错误处理机制,聚焦 router-core 中 not-found-and-errors 主题。
【用途】 TanStack Router 把“未找到”分为两类:一是 URL 路径未匹配路由(自动处理),二是资源不存在这类业务性缺失(在 loader 或 beforeLoad 中手动抛出 notFound())。错误处理则通过按路由配置 errorComponent 边界实现。
【主要能力】
- 全局 404:在根路由上设置 notFoundComponent;也可在创建 router 时用 defaultNotFoundComponent 提供路由级默认 404 组件。
- 按路由 404:在 loader/beforeLoad 中抛出 notFound(),触发未找到边界;可用 notFound({ routeId }) 指定某个父路由处理,或用 rootRouteId 交给根路由。
- notFoundMode:fuzzy(默认)会寻找最近的、拥有子路由且配置了 notFoundComponent 的父路由,尽量保留父级布局;'root' 则把所有未找到错误都交给根路由处理。
- 错误边界:按路由配置 errorComponent,接收 error、info、reset;defaultErrorComponent 提供路由级默认实现。loader 出错时可用 router.invalidate() 重跑 loader,并自动重置错误边界。
- notFoundComponent 中的数据:应使用 useParams、useSearch、useRouteContext 等安全 hook;useLoaderData 可能为 undefined。需要传递部分数据时,可用 notFound({ data }) 的 data 选项,其类型为 unknown,使用前需校验。
- 路由遮蔽:可在 <Link>、useNavigate 上以内联 mask 实现命令式遮蔽,或用 createRouteMask 声明式配置;支持按遮蔽项、按链接或路由级 unmaskOnReload,在刷新时解除遮蔽。
【使用方式】 文档给出完整代码示例:在根路由配置 notFoundComponent,在 router 配置 defaultNotFoundComponent;在 /posts/$postId 的 loader 中查询数据并在缺失时 throw notFound(),配合 notFoundComponent 展示 postId;用 notFound({ routeId: '/_layout' }) 或 rootRouteId 指定处理路由;用 router.invalidate() 实现重试按钮;用 useParams、useSearch、useRouteContext 安全读取数据;用 mask 与 createRouteMask 实现照片弹窗遮蔽。
【适用场景】 适用于使用 TanStack Router 的前端应用需要处理 404、资源缺失、加载失败重试,以及需要在不改变实际渲染路由的前提下展示不同 URL 的弹窗/模态等场景。
【限制与常见错误】
- 不要使用已废弃的 NotFoundRoute,否则 notFound() 与 notFoundComponent 不会生效,应改用 notFoundComponent。
- notFoundComponent 中不可靠地使用 useLoaderData,因 loader 可能尚未完成。
- 只有拥有子路由(因而有 Outlet)的路由才能渲染 notFoundComponent;叶子路由无法捕获路径型未找到错误,会冒泡到最近的有子路由的父级。
- 遮蔽数据存放在 location.state,复制、分享或在新标签页打开 URL 时会丢失遮蔽信息。
- 重试时应使用 router.invalidate()(会重跑 loader 并重置错误边界),仅调用 reset() 只清除错误边界、不会重跑 loader。
与其他主题的交叉引用:notFound() 与 data-loading 中的 loader 数据可用性和错误边界相关;errorComponent 重试依赖 router.invalidate();notFoundComponent 的 data 在 type-safety 中类型为 unknown,使用前需校验。