← [ BACK_TO_NOTES ]

Next.js Error Boundaries

Next.js App Router 的 error.tsx 为 route segment 建立客户端错误边界,用于隔离未处理异常、保留外层 Layout,并通过 reset() 尝试恢复失败子树。

#concept #growing #frame #react

[!info] related notes

Next.js Error Boundaries

一句话定义

error.tsx 是 Next.js App Router 为某个 route segment 建立的错误边界 fallback;当其包裹的子路由树出现未处理异常时,框架可以用错误 UI 替换失败子树,同时尽量保留仍然健康的父级 Layout。

基本模型

目录:

app/
└── (app)/
    ├── layout.tsx
    └── goals/
        ├── error.tsx
        └── [goalId]/page.tsx

如果 [goalId]/page.tsx 中出现未处理异常:

AppLayout             ← 健康,继续保留
└── Goals Boundary
    └── GoalPage      ← 抛出异常
         ↓
      error.tsx       ← 替换失败子树

这体现的是 UI 层的 fault isolation。

为什么 error.tsx 是 Client Component

典型写法:

"use client"

export default function Error({
  error,
  reset,
}: {
  error: Error
  reset: () => void
}) {
  return (
    <div>
      <h2>加载失败</h2>
      <button onClick={() => reset()}>
        重试
      </button>
    </div>
  )
}

这里需要:

onClick
reset()
客户端交互状态

所以 fallback 本身需要客户端运行时。

reset() 的语义

reset() 不是“刷新整个浏览器页面”,而是尝试重新渲染当前错误边界包裹的 route segment。

适合处理:

  • 短暂网络失败
  • 临时后端异常
  • 偶发数据请求失败

不适合掩盖确定性的代码 Bug。如果同一逻辑必然抛错,反复 reset 也不会真正解决问题。

Error Boundary 的层级

错误边界应该尽量靠近真正可能失败、且值得独立恢复的区域。

App Error Boundary
└── Goals Error Boundary
    └── Goal Detail

越近的边界通常越适合提供更具体的恢复 UI;更高层边界负责更大范围的兜底。

这和后端 fault containment 的原则相似:

局部故障优先局部隔离,不要因为一个子页面失败就让整个应用壳一起消失。

一个重要边界:同 segment 的 Layout 错误

不要误以为:

segment/error.tsx

一定能捕获同目录所有文件的异常。

error.tsx 主要包裹该 segment 的子内容;如果错误发生在同 segment 的 layout.tsx 本身,需要由更高一层的错误边界处理。

所以:

segment/layout.tsx 出错
        ↓
需要 parent error boundary

这也是为什么错误边界应该按路由树分层设计,而不是只放一个“万能 error.tsx”。

与通用 React Error Boundary 的关系

Next.js 没有发明“错误边界”这个思想,它是在 React 错误边界机制基础上增加 App Router 文件约定与 route segment 作用域。

通用 React 机制见 声明式错误边界 Error Boundary。

可以这样理解:

React Error Boundary
        ↓ framework convention
Next.js error.tsx
        ↓
route-segment fault isolation

Error 与 Not Found 必须区分

数据库连接失败:

unexpected failure
→ error.tsx

数据库正常查询,但资源不存在:

expected absence
→ notFound()
→ not-found.tsx

不要用:

throw new Error("Goal not found")

把正常 404 伪装成系统异常。见 Next.js Not Found 处理。

与 Layout 状态保留的关系

如果错误发生在 Layout 的子路由中,而 Layout 本身仍健康:

AppLayout
├── Sidebar(collapsed=true)  ← 保留
└── Goals
    └── Error UI

外层 Layout 不需要因为子路由失败而自动重建,因此其中被保留的客户端状态通常也能继续存在。

常见误区

error.tsx 不是业务校验失败的统一入口

诸如“表单邮箱格式错误”“Goal 不存在”不一定属于异常边界。Expected domain outcome 应使用更准确的业务状态表达。

有 error boundary 不等于不用监控

error.tsx 负责用户侧降级 UI,不代表异常就不需要日志、观测和告警。

reset 不是修复 Bug

它只是恢复机制,不是错误处理架构的替代品。

最短记忆方式

error.tsx
= route-level fault boundary
+ fallback UI
+ reset/recovery entry

它主要回答:这一层出现未处理异常时,如何局部失败而不是整棵应用树一起失败?

创建于 2026/9/15 更新于 2026/9/15
Digital Biome
Access

键盘导航

j / k / ↑ / ↓
选择对象
Enter / o
打开选择
/ 或 Ctrl+K
全站搜索
i / f / 1–4
筛选当前列表
g → h / l / p / t / a
首页 / 笔记 / 项目 / 工具 / About
r → 1–9
打开所选对象的关联
u
返回上一页
Esc
关闭浮层 / 取消命令;输入框内清空文本