尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

React Router 的 useRouteError:在错误边界中捕获 loader、action 与渲染错误

React Router 的 useRouteError:在错误边界中捕获 loader、action 与渲染错误 React Router 的 useRouteError在错误边界中捕获 loader、action 与渲染错误【免费下载链接】react-routerDeclarative routing for React项目地址: https://gitcode.com/GitHub_Trending/re/react-routeruseRouteError是 React Router 提供给路由模块ErrorBoundary使用的 Hook用于访问某条路由在其loader、action执行或组件渲染过程中抛出的错误对象。本文围绕当前仓库中的 docs/api/hooks/useRouteError.md 展开结合框架framework模式与数据data模式的实际用法并深入到 packages/react-router/lib/hooks.tsx 的实现源码帮助你掌握useRouteError的调用姿势、返回值的类型收敛技巧以及错误在 React Router 内部被采集与分发的完整链路。功能定位谁能用、何时用useRouteError的两个可用场景由源码 JSDoc 的标注mode framework、mode data直接给出framework 模式在路由模块导出的ErrorBoundary组件中读取错误data 模式配合数据路由对象上的errorElement或渲染级边界读取当前路由的错误。它读取的对象是在路由加载、action提交或组件渲染阶段抛出的异常因此只能在这些错误边界渲染的上下文中调用而不是任意组件都能随意使用。以最典型的路由模块ErrorBoundary为例export function ErrorBoundary() { const error useRouteError(); return div{error.message}/div; }当某条路由的loader、action抛错或该路由组件在渲染中抛错时React Router 不再渲染该路由组件而是改渲染这个ErrorBoundary把错误交给useRouteError()返回。函数签名与返回值function useRouteError(): unknown返回值在官方文档中定义如下在路由loader、action执行或渲染期间抛出的错误。需要特别注意两点返回类型是unknown调用方必须先做类型收敛instanceof Error、isRouteErrorResponse(error)等再访问字段若当前路由/错误边界内没有任何错误通常返回undefined。这样的设计刻意避免了把错误类型臆断为某个具体类——因为 loader/action 中可以抛出任意值普通Error、带status的Response会被规范化为ErrorResponse甚至任意字面量。在路由模块 ErrorBoundary 中落地framework 模式路由模块文档 docs/start/framework/route-module.md 给出了这一用法的完整骨架其核心事实是当其他路由模块 API如loader、action抛错时路由模块ErrorBoundary会代替路由组件渲染。一个“可直接复制”的健壮版错误边界如下它用isRouteErrorResponse区分“HTTP 语义错误”与普通运行时异常import { isRouteErrorResponse, useRouteError, } from react-router; export function ErrorBoundary() { const error useRouteError(); if (isRouteErrorResponse(error)) { return ( div h1 {error.status} {error.statusText} /h1 p{error.data}/p /div ); } else if (error instanceof Error) { return ( div h1Error/h1 p{error.message}/p pThe stack trace is:/p pre{error.stack}/pre /div ); } else { return h1Unknown Error/h1; } }三段分支分别对应分支错误来源示例可访问字段isRouteErrorResponse(error)loader/action抛出Response如throw new Response(Not Found, { status: 404 })被内部规范化为ErrorResponseerror.status、error.statusText、error.dataerror instanceof Errorloader抛出的普通Error对象、组件渲染异常error.message、error.stack其它兜底抛出的字符串、undefined等非标准值——对ErrorResponse判定函数isRouteErrorResponse的详细语义见 docs/api/utils/isRouteErrorResponse.md。data 模式errorElement 中的同一入口useRouteError并不只属于 framework 模式。在 data 模式下数据路由对象通过errorElement为某条路由声明错误边界而该组件内部依然借助useRouteError()取错。仓库的集成测试大量印证了这一对应关系例如在 packages/react-router/tests/dom/data-browser-router-test.tsx 中错误边界组件内部均是let error useRouteError() as ErrorResponse; // 或配合 isRouteErrorResponse(error) 分支渲染 status/statusText也就是说无论你用的是 createBrowserRouter/createMemoryRouter 等数据路由器的errorElement还是 framework 约定的模块级ErrorBoundary取错入口统一都是useRouteError。两者唯一的差异是错误边界由谁承载、错误被记在哪一层。源码解读错误究竟从哪里来useRouteError的实现位于 packages/react-router/lib/hooks.tsx一共只有十余行export function useRouteError(): unknown { let error React.useContext(RouteErrorContext); let state useDataRouterState(DataRouterStateHook.UseRouteError); let routeId useCurrentRouteId(DataRouterStateHook.UseRouteError); // If this was a render error, we put it in a RouteError context inside // of RenderErrorBoundary if (error ! undefined) { return error; } // Otherwise look for errors from our data router state return state.errors?.[routeId]; }从源码结构看错误有两个来源通道useRouteError按优先级依次查找渲染期错误Render Error——来自 React ContextRouteErrorContext定义于 packages/react-router/lib/context.ts。当组件渲染抛错时React Router 内部类组件RenderErrorBoundaryhooks.tsx通过static getDerivedStateFromError(error)捕获异常并在render()中把错误写入RouteErrorContext.Provider value{error}hooks.tsx随后渲染传入的错误边界组件于是边界内调用useRouteError()即可从 Context 直接取出该错误。数据层错误loader/action Error——来自数据路由状态action、loader抛出的错误并不会触发 React 的渲染异常捕获而是被数据路由器记录在全局状态state.errors按routeId索引。因此useRouteError还需要通过useDataRouterState拿到状态再取state.errors?.[routeId]。RenderErrorBoundary源码还透露了两处值得注意的行为错误会随 location 变化而重置getDerivedStateFromProps中当state.location与新的props.location不一致或一次 revalidation 从非 idle 回到 idle时会以新 props 的错误重置状态hooks.tsx从而保证用户“后退/前进”到无错路由时能自动从错误页恢复。RSC digest 会被解码在 RSC 场景下若错误对象携带字符串类型的digest字段渲染前会先尝试decodeRouteErrorResponseDigest(error.digest)还原出真实错误hooks.tsx。此外在 components 侧错误边界组件会被withErrorBoundaryProps包装统一注入params、loaderData、actionData与error即useRouteError()的返回值见 packages/react-router/lib/components.tsx——这说明useRouteError也正是框架级默认错误边界实现读取错误的底层入口。使用边界与注意事项综合官方文档与源码使用时有几条需要记牢的约束只能在错误边界内调用useRouteError依赖RouteErrorContext或state.errors[routeId]脱离边界调用通常拿不到任何错误返回undefined没有实际意义。不要假定返回类型签名是(): unknown访问error.message、error.status前必须完成类型收敛isRouteErrorResponse、instanceof Error、或对 RSC 场景额外检查error.data。framework 与 data 模式语义一致但承载不同framework 模式绑定模块导出ErrorBoundarydata 模式绑定路由对象errorElement不要把在普通页面组件中调用它当成“全局取错”的手段。抛Response能拿到 HTTP 语义在loader/action里throw new Response(...)或使用throw redirect(...)等错误边界中用isRouteErrorResponse判断后即可渲染status/statusText/data这也是实现“404 / 500 页面”的推荐姿势。深入阅读本文档来源docs/api/hooks/useRouteError.md路由模块各 API 与ErrorBoundary约定docs/start/framework/route-module.md错误边界设计完整指南docs/how-to/error-boundary.mdErrorResponse判定与字段docs/api/utils/isRouteErrorResponse.md实现源码packages/react-router/lib/hooks.tsx、Context 定义 packages/react-router/lib/context.ts、渲染边界类 packages/react-router/lib/hooks.tsx测试证据data 模式错误边界使用样例见 packages/react-router/tests/dom/data-browser-router-test.tsx【免费下载链接】react-routerDeclarative routing for React项目地址: https://gitcode.com/GitHub_Trending/re/react-router创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表