TanStack Start Error Boundaries 错误边界与错误页面

在 TanStack Start 中实现全面的错误处理,涵盖路由级错误边界、服务器函数错误处理、自定义错误页面和错误监控。

Sam Rivera
Sam Rivera
June 1, 202610 min read
其他语言:Deutsch · English

TL;DR: TanStack Start 和 TanStack Router 提供了一套分层错误处理系统:路由级 errorComponent、全局错误边界,以及服务器函数 try/catch 模式。本指南涵盖按路由自定义错误页面、全局错误监控集成、带友好用户消息的服务器端优雅错误处理,以及错误恢复流程。


引言

错误处理常常被当作事后补救,但它直接影响用户信任度和留存率。一条神秘的"出了点问题"消息会让用户沮丧。而一个设计精良的错误页面——提供上下文背景、恢复选项和联系支持的方式——则能增强用户信心。

TanStack Start 提供了多层错误处理机制,从 React 错误边界到服务端错误映射。


路由级错误组件

TanStack Router 允许你为每个路由定义 errorComponent,让你对错误展示有细粒度的控制。以下是一个仪表盘路由,配备了自定义错误组件,可区分认证错误和通用故障:

tsx
// src/routes/dashboard.tsx
import { createFileRoute } from '@tanstack/react-router'
import { ErrorComponent } from '@tanstack/react-router'

export const Route = createFileRoute('/dashboard')({
  component: DashboardPage,
  errorComponent: ({ error, reset }) => (
    <div className="p-8 text-center">
      <h2 className="text-xl font-bold mb-2">仪表盘错误</h2>
      <p className="text-gray-600 mb-4">
        {error instanceof AuthError
          ? '您的会话已过期,请重新登录。'
          : '无法加载仪表盘,请重试。'}
      </p>
      <div className="flex gap-4 justify-center">
        <button onClick={reset} className="btn-primary">重试</button>
        <a href="/login" className="btn-secondary">登录</a>
      </div>
      <details className="mt-4 text-xs text-gray-400">
        <summary>技术详情</summary>
        <pre>{error.message}</pre>
      </details>
    </div>
  ),
})

errorComponent 接收 error 对象和一个 reset 函数。reset 函数清除错误边界并重新渲染路由,让用户无需离开页面就能获得恢复路径。对错误进行分类(认证 vs 通用)可以让你展示符合上下文的错误消息。

全局错误边界

对于逃脱路由级处理的错误,在根路由中设置全局错误边界。这会捕获所有子路由中的任何未处理错误:

tsx
// src/routes/__root.tsx
import { createRootRoute, Outlet } from '@tanstack/react-router'

export const Route = createRootRoute({
  component: () => (
    <ErrorBoundary fallback={<GlobalErrorPage />}>
      <Outlet />
    </ErrorBoundary>
  ),
})

全局错误边界充当安全网。如果路由级 errorComponent 失败或有意外错误向上传播,全局边界会渲染一个覆盖整个应用的备用 UI。

服务器函数错误处理

服务器函数应在错误到达客户端之前捕获并分类错误。以下模式将数据库错误与其他故障区分开来,记录关键问题同时返回用户友好的消息:

tsx
export const fetchDataFn = createServerFn({ method: 'GET' })
  .handler(async () => {
    try {
      return await loadData()
    } catch (error) {
      if (error instanceof DatabaseError) {
        // 记录以供监控
        console.error('数据库错误:', error)
        // 返回用户友好的响应
        return { error: '数据暂时不可用', retryAfter: 30 }
      }
      throw error // 让中间件处理
    }
  })

这种方法保持客户端代码简洁:服务器函数要么返回数据,要么返回结构化错误响应,客户端相应地处理每种情况,无需解析错误消息。

错误处理策略表

层级捕获内容用户看到恢复方式
Zod 验证无效输入字段错误修复输入
服务器函数业务逻辑错误消息 + 重试重试或联系
路由 errorComponent路由加载错误自定义错误页面重试或导航
全局 ErrorBoundary任何未捕获错误备用页面刷新或联系支持
onError(变更)变更失败提示回滚 UI

结语

TanStack Start 的分层错误处理让你能够控制每种故障模式。路由级错误组件提供符合上下文的恢复方式,而全局边界则捕获任何漏网之鱼。若要更深入的集成,可将错误边界与中间件和请求生命周期模式结合,将其与嵌套布局和认证守卫配对以保护路由,并接入 SaaS 监控与可观测性 以进行生产环境错误追踪。