本文档介绍 TanStack Router 中「未找到(Not Found)」与「错误(Errors)」两类处理机制。
【用途】 TanStack Router 处理两类「not found」:一是 URL 路径未匹配(自动处理),二是资源缺失,例如请求的文章不存在(需通过 notFound() 手动抛出)。错误边界则通过每个路由的 errorComponent 配置。
【重要提醒】 不要使用已废弃的 NotFoundRoute。当它存在时,notFound() 和 notFoundComponent 将不会工作,应移除它并改用 notFoundComponent。另外,在 notFoundComponent 内部 useLoaderData 可能为 undefined,应改用 useParams、useSearch 或 useRouteContext。
【未找到处理】
- 全局 404:在根路由上配置 notFoundComponent。
- 路由器级默认:通过 createRouter 的 defaultNotFoundComponent 配置。
- 按路由 404(资源缺失):在 loader 或 beforeLoad 中当资源不存在时抛出 notFound(),其工作方式类似 redirect(),通过抛出以触发 not-found 边界。
- 指定目标路由:可用 notFound({ routeId }) 强制某个父路由处理,或使用 rootRouteId 指向根路由。
【notFoundMode:fuzzy 与 root】 fuzzy(默认):路由器寻找最近的、拥有子路由且有 notFoundComponent 的父路由,尽可能保留父级布局。以 root → posts → $postId 为例,访问 /posts/1/edit 时依次渲染 Root、Posts,然后渲染 Posts.notFoundComponent。root:所有 not-found 错误都交给根路由的 notFoundComponent,无论匹配情况如何。
【错误处理】
- 每个路由的 errorComponent:接收 error、info、reset 属性。对于 loader 错误,使用 router.invalidate() 重新运行 loader,它会自动重置错误边界。
- 路由器级默认错误组件:通过 defaultErrorComponent 配置。
【notFoundComponent 中的数据】 notFoundComponent 无法可靠使用 useLoaderData,因为 loader 可能尚未完成。安全可用的钩子包括 useParams、useSearch、useRouteContext。若需传递部分数据,可使用 notFound() 的 data 选项,其 data 类型为 unknown,使用前需校验。
【路由遮罩 Route Masking】 路由遮罩让浏览器地址栏显示与实际渲染路由不同的 URL。遮罩数据存储在 location.state 中,当 URL 被分享或在新标签页打开时会丢失。支持在 Link 上做命令式遮罩、使用 useNavigate 做命令式遮罩,以及用 createRouteMask 做声明式遮罩。默认情况下遮罩在本地页面重载后仍保留,可通过单条遮罩、单个链接或路由器级(unmaskOnReload: true)配置在重载时取消遮罩。
【常见错误】
- 使用已废弃的 NotFoundRoute,会阻止 notFound() 和 notFoundComponent 生效,应改用根路由上的 notFoundComponent。
- 在 notFoundComponent 中期望使用 useLoaderData,此时 loader 可能未完成;应改用安全钩子。
- 叶子路由无法处理 not-found 错误:只有拥有子路由(因而有 Outlet)的路由才能渲染 notFoundComponent,叶子路由不会捕获 not-found 错误,错误会冒泡到最近的拥有子路由的父路由。
- 期望被遮罩的 URL 在分享后仍生效:遮罩数据存于 location.state(浏览器历史)中,被复制、分享或在新标签页打开时会丢失,浏览器会直接导航到可见的(被遮罩的)URL。
- 仅使用 reset() 而非 router.invalidate():reset() 会清除错误边界但不会重新运行 loader;应使用 router.invalidate() 来重跑 loader 并重置错误边界。
【交叉引用】 router-core/data-loading:loader 中抛出的 notFound() 与错误边界及 loader 数据可用性交互;errorComponent 重试需要 router.invalidate()。router-core/type-safety:notFoundComponent 的 data 类型为 unknown,使用前需校验。