错误处理
error.js
文件约定允许您在
嵌套路由
中优雅地处理意外的运行时错误。
- 自动将路由段及其嵌套子项包装在 React 错误边界中。
- 使用文件系统层次结构调整细粒度,为特定段定制错误 UI。
- 将错误隔离到受影响的段,同时保持应用程序的其余部分正常运作。
- 添加尝试从错误中恢复而无需完全重新加载页面的功能。
通过在路由段内部添加 error.js
文件并导出一个 React 组件来创建错误 UI:
import { useEffect } from 'react';
export default function Error({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
useEffect(() => {
// 将错误记录到错误报告服务
console.error(error);
}, [error]);
return (
<div>
<h2>出了点问题!</h2>
<button
onClick={() =>
// 尝试通过尝试重新渲染段来恢复
reset()
}
>
重试
</button>
</div>
);
}
error.js 的工作原理
error.js
自动创建一个 React 错 误边界, 包装一个嵌套的子段或page.js
组件。- 从
error.js
文件导出的 React 组件用作回退组件。 - 如果在错误边界内引发错误,则错误被包含,将渲染回退组件。
- 当回退错误组件处于活动状态时,位于错误边界上方的布局保持其状态并保持交互性,错误组件可以显示从错误中恢复的功能。
从错误中恢复
错误的原因有时可能是临时的。在这些情况下,简单地重试可能会解决问题。
错误组件可以使用 reset()
函数提示用户尝试从错误中恢复。
执行该函数时,将尝试重新渲染错误边界的内容。
如果成功,回退错误组件将被重新渲染的结果替换。
'use client'
export default function Error({
error,
reset,
}: {
error: Error & { digest?: string }
reset: () => void
}) {
return (
<div>
<h2>Something went wrong!</h2>
<button onClick={() => reset()}>Try again</button>
</div>
)
}
嵌套路由
通过特殊文件创建的 React 组件以特定的嵌套层次结构进行呈现。
例如,具有两个包含 layout.js
和 error.js
文件的段的嵌套路由以以下简化的组件层次结构进行呈现:
嵌套组件层次结构对于跨嵌套路由的 error.js
文件 的行为有影响:
- 错误会冒泡到最近的父错误边界。这意味着
error.js
文件将处理所有其嵌套子段的错误。 通过在嵌套路由的不同级别放置error.js
文件,可以实现更或更少粒度的错误 UI。 - 错误边界不会处理在同一段中的
layout.js
组件中引发的错误,因为错误边界嵌套在该布局的组件内部。
处理布局中的错误
error.js
边界不会捕获在同一段的 layout.js
或 template.js
组件中引发的错误。
这种有意的层次结构保持了在发生错误时共享的重要 UI(如导航)可见且可交互。
要处理特定布局或模板中的错误,请在布局的父段中放置一个 error.js
文件。
要在根布局或模板中处理错误,请使用名为 global-error.js
的 error.js
变体。
处理根布局中的错误
根 app/error.js
边界不会捕获在根 app/layout.js
或 app/template.js
组件中引发的错误。
要专门处理这些根组件中的错误,请使用名为 app/global-error.js
的 error.js
变体,位于根 app
目录中。
与根 error.js
不同,global-error.js
错误边界包装整个应用程序,并在活动时用其回退组件替换根布局。
因此,请注意,global-error.js
必须定义自己的 <html>
和 <body>
标签。
global-error.js
是最不粒度的错误 UI,可以被视为整个应用程序的“全能处理”错误处理。
由于根组件通常不太动态,而其他 error.js
边界将捕获大多数错误,因此很少触发。
即使定义了 global-error.js
,仍建议定义一个根 error.js
,其回退组件将在根布局中呈现,其中包括全局共享的 UI 和品牌。
'use client'
export default function GlobalError({
error,
reset,
}: {
error: Error & { digest?: string }
reset: () => void
}) {
return (
<html>
<body>
<h2>Something went wrong!</h2>
<button onClick={() => reset()}>Try again</button>
</body>
</html>
)
}
处理服务器错误
如果在 Server Component 内引发错误,Next.js 将将 Error 对象(在生产中剥离了敏感错误信息的对象)
转发到最近的 error.js
文件,作为 error
属性。