ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Solid Start 错误边界完全指南:defaultErrorComponent 与 errorComponent 的路由级错误处理实战

Solid Start 错误边界完全指南:defaultErrorComponent 与 errorComponent 的路由级错误处理实战 Solid Start 错误边界完全指南defaultErrorComponent 与 errorComponent 的路由级错误处理实战【免费下载链接】router A client-first, server-capable, fully type-safe router and full-stack framework for the web (React and more).项目地址: https://gitcode.com/GitHub_Trending/ro/routerSolid Start 自身并不另起炉灶设计错误处理体系而是直接复用tanstack/solid-router的路由级错误边界能力你可以在创建路由器时通过defaultErrorComponent设置全局兜底错误组件也可以在每个路由上用errorComponent做局部覆盖从而统一捕获beforeLoad、loader以及组件渲染阶段抛出的异常。读完本文你将掌握 Solid Start 中错误边界的两种配置方式、ErrorComponentPropserror/info/reset的底层语义以及「失败后如何重试」的正确姿势。一、Solid Start 错误边界文档的定位与来源仓库中 Solid 框架的错误边界指南位于 docs/start/framework/solid/guide/error-boundaries.md它的正文通过 frontmatter 的ref/replace机制复用 React 版文档--- ref: docs/start/framework/react/guide/error-boundaries.md replace: { tanstack/react-router: tanstack/solid-router, React Start: Solid Start, } ---也就是说Solid 版指南的实际内容来自 docs/start/framework/react/guide/error-boundaries.md并在渲染时将tanstack/react-router替换为tanstack/solid-router、React Start替换为Solid Start。这从侧面印证了一个核心事实错误边界机制属于 TanStack Router 的路由层能力React / Solid / Vue 各框架共享同一套设计本文以下示例均以 Solid 生态的tanstack/solid-router为准。二、错误边界的整体设计两个层级官方指南将路由级错误边界概括为两个层级路由器级默认default通过createRouter的defaultErrorComponent为所有路由设置默认错误 UI当错误一路冒泡到路由器时展示路由级覆盖per-route通过每个路由的errorComponent为特定路由定制专属错误 UI。从源码可以看到Solid 路由器的选项类型中明确定义了该配置项packages/solid-router/src/router.ts#L33defaultErrorComponent?: ErrorRouteComponent而在路由选项扩展中errorComponent的类型被设计为false | null | undefined | ErrorRouteComponentpackages/solid-router/src/route.tsx#L56-L61这意味着你不仅可以用自定义组件覆盖还可以显式传false关闭某个路由的错误边界。两个层级的优先级在渲染时体现为一条明确的回退链route.options.errorComponent ?? router.options.defaultErrorComponent ?? ErrorComponent见 packages/solid-router/src/Match.tsx#L255-L258。即路由级配置优先其次才是路由器全局默认最后兜底使用内置的ErrorComponent。三、配置全局默认错误组件defaultErrorComponent在 Solid Start 中路由器通常在src/router.tsx或routeTree.gen生成后创建。为所有未单独配置错误组件的路由设置兜底 UI// src/router.tsx import { createRouter, ErrorComponent } from tanstack/solid-router import { routeTree } from ./routeTree.gen export function getRouter() { const router createRouter({ routeTree, // 当错误冒泡到路由器时展示的默认错误 UI defaultErrorComponent: ({ error, reset }) ( ErrorComponent error{error} / ), }) return router }这里的defaultErrorComponent收到的 props 就是ErrorComponentProps包含error与reset详见下文第五节。注意 Solid 组件统一接收单个 props 对象因此这里直接解构{ error, reset }即可。从源码结构看路由内容会被CatchBoundary包裹packages/solid-router/src/Match.tsx#L58-L59 与 #L117-L119CatchBoundary内部基于 Solid 自带的ErrorBoundary实现捕获逻辑packages/solid-router/src/CatchBoundary.tsx#L6-L46Solid.ErrorBoundary fallback{(error, reset) { props.onCatch?.(error) Solid.createEffect( Solid.on(props.getResetKey, () reset(), { defer: true }), ) return ( Dynamic component{props.errorComponent ?? ErrorComponent} error{error} reset{reset} / ) }} {props.children} /Solid.ErrorBoundary由此可见「全局默认」的本质每个路由渲染时都会先尝试自身errorComponent若未配置才回落到路由器的defaultErrorComponent。四、路由级覆盖errorComponent当某个路由需要专属的错误体验例如文章详情页展示「文章不存在」而不是通用错误页时在文件路由中配置errorComponent// src/routes/posts.$postId.tsx import { createFileRoute, ErrorComponent } from tanstack/solid-router import type { ErrorComponentProps } from tanstack/solid-router function PostError(props: ErrorComponentProps) { return ErrorComponent error{props.error} / } export const Route createFileRoute(/posts/$postId)({ component: PostComponent, errorComponent: PostError, })几点值得注意errorComponent优先级高于defaultErrorComponent二者形成「特殊路由特殊处理、其余路由统一兜底」的覆盖模型若传errorComponent: false可显式禁用该路由的错误边界让错误继续向祖先路由或全局边界冒泡类型定义见 packages/solid-router/src/route.tsx#L58createFileRoute生成的Route会与routeTree.gen中该路由的配置合并这也是文件路由体系下最常见的写法。五、ErrorComponentPropserror、info 与 reset 的底层语义所有错误组件的 props 统一由tanstack/router-core定义packages/router-core/src/route.ts#L1596-L1615export interface ErrorBoundaryTypes { error: unknown } export type ErrorComponentPropsTError ErrorBoundaryTypes[error] { error: TError info?: { componentStack: string } reset: () void }其中error被捕获的异常对象info可选的组件栈信息componentStack便于定位渲染期的错误来源reset重置错误边界、重新渲染路由内容的方法。值得注意的是旧类型ErrorRouteProps已被标记为deprecatedpackages/router-core/src/route.ts#L1595-L1602新代码应统一使用ErrorComponentProps。各框架还可以对error类型做特化。Solid 就在 packages/solid-router/src/route.tsx#L51-L54 中通过模块声明收窄了错误类型declare module tanstack/router-core { export interface ErrorBoundaryTypes { error: Error } }也就是说在 Solid 生态中错误组件收到的error会被归一化为Error实例。这一归一化逻辑在 packages/solid-router/src/Match.tsx#L241-L284 中可见服务端渲染路径会把非Error的抛出值包装成new Error(...)并保留cause指向原始值客户端路径则直接throw currentMatch().error交由CatchBoundary里的 SolidErrorBoundary捕获。六、内置 ErrorComponent开箱即用的默认 UI如果不提供任何自定义错误组件回退链的终点是内置的ErrorComponentpackages/solid-router/src/CatchBoundary.tsx#L48-L89。它渲染一个简单的错误面板标题文案为 Something went wrong!提供一个 Show Error / Hide Error 切换按钮用于展开/收起错误详情错误详情以红色pre代码块展示error.message默认显隐行为与NODE_ENV相关非生产环境默认展开错误信息便于开发调试生产环境则默认收起避免向用户泄露内部细节。这个组件纯粹是「简单可用」的占位实现官方指南明确说明它是可以随意替换的——无论是自定义样式、接入错误上报如 Sentry还是展示更友好的用户界面替换掉它即可。七、错误从哪里来beforeLoad 与 loader 抛错错误边界能捕获的错误来源包括beforeLoad阶段抛出的错误如权限校验失败loader中抛出的错误如接口请求失败、数据未找到组件渲染过程中抛出的错误由CatchBoundary包裹的渲染内容触发。仓库测试 packages/solid-router/tests/errorComponent.test.tsx 与 packages/react-router/tests/errorComponent.test.tsx 对此有充分覆盖例如「beforeLoad抛出原始类型错误时错误组件仍能收到并渲染」以及「路由错误组件在后台子代路由恢复后自动重置」等场景。React 侧测试 packages/react-router/tests/errorComponent.test.tsx#L387-L407 展示了从beforeLoad抛出new Error的断言方式Solid 侧行为与之对齐。八、失败后如何重试reset 与 router.invalidate() 的分工这是最容易踩坑的一点。官方指南与仓库内部技能文档packages/router-core/skills/router-core/not-found-and-errors/SKILL.md都强调了两者的区别reset()清除错误边界状态、重新渲染路由内容。它适合「状态已被修复、重新渲染即可恢复」的场景例如用户在错误 UI 上修正了某个本地状态后点击重试router.invalidate()重新执行路由的 loaders并自动重置错误边界。如果错误来自 loader 数据加载仅调用reset()并不会重新拉取数据——错误边界被重置后 loader 仍持有旧的失败结果正确的做法是调用router.invalidate()让它重跑 loader。参考实现packages/router-core/skills/router-core/not-found-and-errors/SKILL.md#L413-L444中给出的正确重试模式function ErrorFallback(props: { error: unknown; reset: () void }) { return ( button onClick{() props.reset()}Retry/button ) } // 若错误源于 loader应改为 // onClick{() router.invalidate()}在真实应用中常见的组合是错误 UI 上提供「重试」按钮若错误属于数据加载失败则调用router.invalidate()若属于纯渲染/状态问题则调用reset()。CatchBoundary还通过getResetKey在路由变化等场景下自动触发重置见 packages/solid-router/src/CatchBoundary.tsx#L19-L21后台子代路由恢复后祖先错误边界会自动复位这与测试 packages/solid-router/tests/errorComponent.test.tsx#L217 覆盖的行为一致。九、实践清单先配全局在createRouter中设置defaultErrorComponent保证任何未被局部覆盖的错误都有兜底 UI再改局部对需要差异化体验的路由详情页、表单页等用errorComponent覆盖必要时传false关闭边界善用 reset / invalidate渲染态错误用reset()数据加载错误用router.invalidate()替换内置 UI把ErrorComponent替换为符合产品风格、接入日志上报的自定义组件利用类型收窄Solid 下error已被收窄为Error可直接读取error.message无需再判断是否为Error实例跨框架注意 React 侧error类型为unknown。错误边界是 Solid Start 应用健壮性的最后一道防线把「默认兜底」与「局部定制」配合好配合reset/invalidate的重试语义就能以极少的样板代码获得覆盖数据加载、权限校验与渲染异常的全链路错误处理。【免费下载链接】router A client-first, server-capable, fully type-safe router and full-stack framework for the web (React and more).项目地址: https://gitcode.com/GitHub_Trending/ro/router创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表