Skip to main content

错误处理

error.js 文件约定允许你优雅地处理 嵌套路由 中意外的运行时错误。

¥The error.js file convention allows you to gracefully handle unexpected runtime errors in nested routes.

  • 自动将路由段及其嵌套子级封装在 React 误差边界 中。

    ¥Automatically wrap a route segment and its nested children in a React Error Boundary.

  • 使用文件系统层次结构创建针对特定段的错误 UI 来调整粒度。

    ¥Create error UI tailored to specific segments using the file-system hierarchy to adjust granularity.

  • 将错误隔离到受影响的段,同时保持应用的其余部分正常运行。

    ¥Isolate errors to affected segments while keeping the rest of the application functional.

  • 添加功能以尝试从错误中恢复而无需重新加载整页。

    ¥Add functionality to attempt to recover from an error without a full page reload.

通过在路由段内添加 error.js 文件并导出 React 组件来创建错误 UI:

¥Create error UI by adding an error.js file inside a route segment and exporting a React component:

'use client' // Error components must be Client Components

import { useEffect } from 'react'

export default function Error({
error,
reset,
}: {
error: Error & { digest?: string }
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>
)
}
'use client' // Error components must be Client Components

import { useEffect } from 'react'

export default function Error({ error, reset }) {
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 的工作原理

¥How error.js Works

  • error.js 自动创建一个封装嵌套子段或 page.js 组件的 React 误差边界

    ¥error.js automatically creates a React Error Boundary that wraps a nested child segment or page.js component.

  • error.js 文件导出的 React 组件用作后备组件。

    ¥The React component exported from the error.js file is used as the fallback component.

  • 如果在错误边界内抛出错误,则错误将被包含,并渲染后备组件。

    ¥If an error is thrown within the error boundary, the error is contained, and the fallback component is rendered.

  • 当回退错误组件处于活动状态时,错误边界上方的布局将保持其状态并保持交互,并且错误组件可以显示从错误中恢复的功能。

    ¥When the fallback error component is active, layouts above the error boundary maintain their state and remain interactive, and the error component can display functionality to recover from the error.

从错误中恢复

¥Recovering From Errors

错误的原因有时可能是暂时的。在这些情况下,只需重试即可解决问题。

¥The cause of an error can sometimes be temporary. In these cases, simply trying again might resolve the issue.

错误组件可以使用 reset() 函数来提示用户尝试从错误中恢复。执行时,该函数将尝试重新渲染错误边界的内容。如果成功,后备错误组件将替换为重新渲染的结果。

¥An error component can use the reset() function to prompt the user to attempt to recover from the error. When executed, the function will try to re-render the Error boundary's contents. If successful, the fallback error component is replaced with the result of the re-render.

'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>
)
}
'use client'

export default function Error({ error, reset }) {
return (
<div>
<h2>Something went wrong!</h2>
<button onClick={() => reset()}>Try again</button>
</div>
)
}

嵌套路由

¥Nested Routes

通过 特殊文件 创建的 React 组件在 特定的嵌套层次结构 中渲染。

¥React components created through special files are rendered in a specific nested hierarchy.

例如,包含 layout.jserror.js 文件的两个段的嵌套路由将在以下简化的组件层次结构中渲染:

¥For example, a nested route with two segments that both include layout.js and error.js files are rendered in the following simplified component hierarchy:

嵌套组件层次结构对嵌套路由中 error.js 文件的行为有影响:

¥The nested component hierarchy has implications for the behavior of error.js files across a nested route:

  • 错误会向上冒泡到最近的父错误边界。这意味着 error.js 文件将处理其所有嵌套子段的错误。通过将 error.js 文件放置在路由的嵌套文件夹中的不同级别,可以实现或多或少的粒度错误 UI。

    ¥Errors bubble up to the nearest parent error boundary. This means an error.js file will handle errors for all its nested child segments. More or less granular error UI can be achieved by placing error.js files at different levels in the nested folders of a route.

  • error.js 边界不会处理同一段中 layout.js 组件中抛出的错误,因为错误边界嵌套在该布局的组件内。

    ¥An error.js boundary will not handle errors thrown in a layout.js component in the same segment because the error boundary is nested inside that layout's component.

处理布局中的错误

¥Handling Errors in Layouts

error.js 边界不会捕获同一段的 layout.jstemplate.js 组件中抛出的错误。当发生错误时,此 有意的等级制度 使同级路由之间共享的重要 UI(例如导航)保持可见且可用。

¥error.js boundaries do not catch errors thrown in layout.js or template.js components of the same segment. This intentional hierarchy keeps important UI that is shared between sibling routes (such as navigation) visible and functional when an error occurs.

要处理特定布局或模板中的错误,请将 error.js 文件放置在布局的父段中。

¥To handle errors within a specific layout or template, place an error.js file in the layout's parent segment.

要处理根布局或模板中的错误,请使用 error.js 的变体(称为 global-error.js)。

¥To handle errors within the root layout or template, use a variation of error.js called global-error.js.

处理根布局中的错误

¥Handling Errors in Root Layouts

app/error.js 边界不会捕获根 app/layout.jsapp/template.js 组件中引发的错误。

¥The root app/error.js boundary does not catch errors thrown in the root app/layout.js or app/template.js component.

要专门处理这些根组件中的错误,请使用位于根 app 目录中的 error.js 变体(称为 app/global-error.js)。

¥To specifically handle errors in these root components, use a variation of error.js called app/global-error.js located in the root app directory.

与根 error.js 不同,global-error.js 错误边界封装了整个应用,并且其后备组件在活动时替换根布局。因此,需要注意的是,global-error.js 必须定义自己的 <html><body> 标签。

¥Unlike the root error.js, the global-error.js error boundary wraps the entire application, and its fallback component replaces the root layout when active. Because of this, it is important to note that global-error.js must define its own <html> and <body> tags.

global-error.js 是最细粒度的错误 UI,可以被视为整个应用的 "catch-all" 错误处理。它不太可能经常被触发,因为根组件通常不太动态,并且其他 error.js 边界将捕获大多数错误。

¥global-error.js is the least granular error UI and can be considered "catch-all" error handling for the whole application. It is unlikely to be triggered often as root components are typically less dynamic, and other error.js boundaries will catch most errors.

即使定义了 global-error.js,仍然建议定义根 error.js,其后备组件将在根布局中渲染,其中包括全局共享的 UI 和品牌。

¥Even if a global-error.js is defined, it is still recommended to define a root error.js whose fallback component will be rendered within the root layout, which includes globally shared UI and branding.

'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>
)
}
'use client'

export default function GlobalError({ error, reset }) {
return (
<html>
<body>
<h2>Something went wrong!</h2>
<button onClick={() => reset()}>Try again</button>
</body>
</html>
)
}

很高兴知道:

¥Good to know:

  • global-error.js 仅在生产中启用。在开发过程中,我们的错误叠加将会显示。

    ¥global-error.js is only enabled in production. In development, our error overlay will show instead.

处理服务器错误

¥Handling Server Errors

如果服务器组件内部抛出错误,Next.js 会将 Error 对象(在生产中去除敏感错误信息)转发到最近的 error.js 文件作为 error 属性。

¥If an error is thrown inside a Server Component, Next.js will forward an Error object (stripped of sensitive error information in production) to the nearest error.js file as the error prop.

保护敏感错误信息

¥Securing Sensitive Error Information

在生产过程中,转发到客户端的 Error 对象仅包含通用 messagedigest 属性。

¥During production, the Error object forwarded to the client only includes a generic message and digest property.

这是一项安全预防措施,以避免将错误中包含的潜在敏感详细信息泄露给客户端。

¥This is a security precaution to avoid leaking potentially sensitive details included in the error to the client.

message 属性包含有关错误的通用消息,digest 属性包含自动生成的错误哈希,可用于匹配服务器端日志中的相应错误。

¥The message property contains a generic message about the error and the digest property contains an automatically generated hash of the error that can be used to match the corresponding error in server-side logs.

在开发过程中,转发到客户端的 Error 对象将被序列化,并包含原始错误的 message,以便于调试。

¥During development, the Error object forwarded to the client will be serialized and include the message of the original error for easier debugging.