Error.js 的作用
使用 error.js 文件规则,可以优雅地处理嵌套路由中的意外运行时错误。
在 React Error Boundary 中自动封装路由段及其嵌套子段。
使用文件系统层次结构来调整粒度,为特定网段量身定制错误 UI。
将错误隔离到受影响的网段,同时保持应用程序其他部分的功能。
添加功能,尝试在不重新加载整个页面的情况下从错误中恢复。
通过在路由段内添加 error.js 文件并导出 React 组件来创建错误用户界面:
// app/dashboard/error.tsx
'use client' // Error components must be Client Components
import { useEffect } from 'react'
export default function Error({
error,
reset,
}: {
error: Error
reset: () => void
}) {
useEffect(() => {
// Log the error to an error reporting service
console.error(error)
}, [error])
return (
<div>
<h2>Something went wrong!</h2>
<button
onClick={
// Attempt to recover by trying to re-render the segment
() => reset()
}
>
Try again
</button>
</div>
)
}
Error.js 的工作原理
error.js 会自动创建一个 React 错误边界,该边界会封装嵌套的子段或 page.js 组件。
从 error.js 文件导出的 React 组件将用作后备组件。
如果在错误边界内出现错误,则会包含错误并呈现回退组件。
当回退错误组件处于活动状态时,错误边界上方的布局会保持其状态并保持交互,而错误组件则可以显示从错误中恢复的功能。
从错误中恢复
错误的原因有时可能是暂时的。在这种情况下,只需再次尝试就能解决问题。
错误组件可以使用 reset() 函数提示用户尝试从错误中恢复。该函数执行后,将尝试重新渲染错误边界的内容。如果成功,回退错误组件将被重新渲染的结果所取代。
嵌套路由
通过特殊文件创建的 React 组件会以特定的嵌套层次结构呈现。
例如,一个嵌套路由有两个段,其中都包含 layout.js 和 error.js 文件,会以以下简化的组件层次结构呈现:
嵌套组件层次结构会影响整个嵌套路由中 error.js 文件的行为:
错误会向最近的父错误边界冒泡。这意味着 error.js 文件将处理其所有嵌套子段的错误。通过将 error.js 文件放置在路由嵌套文件夹的不同层级,可以实现更细粒度或更小粒度的错误用户界面。
error.js 界面不会处理同一段落中 layout.js 组件抛出的错误,因为错误边界嵌套在该布局组件中。
处理根布局中的错误
根 app/error.js 界面不会捕获在根 app/layout.js 或 app/template.js 组件中抛出的错误。
要专门处理这些根组件中的错误,可使用应用程序根目录中名为 app/global-error.js 的 error.js 变体。
与根 error.js 不同的是,global-error.js 的错误边界覆盖了整个应用程序,其回退组件会在激活时替换根布局。因此,必须注意 global-error.js 必须定义自己的 <html> 和 <body> 标记。
global-error.js 是粒度最小的错误用户界面,可视为整个应用程序的 "万能 "错误处理。它不太可能经常被触发,因为根组件的动态性通常较低,其他 error.js 界面会捕捉到大多数错误。
即使定义了 global-error.js,仍建议定义一个根 error.js,其后备组件将在根布局中呈现,其中包括全局共享的用户界面。
// app/global-error.tsx
'use client'
export default function GlobalError({
error,
reset,
}: {
error: Error
reset: () => void
}) {
return (
<html>
<body>
<h2>Something went wrong!</h2>
<button onClick={() => reset()}>Try again</button>
</body>
</html>
)
}