Skip to content

Commit 334c8eb

Browse files
docs: update documentation translations (#11)
Co-authored-by: xiaoyu2er <xiaoyu2er@users.noreply.github.com>
1 parent b2768b5 commit 334c8eb

File tree

100 files changed

+13566
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

100 files changed

+13566
-0
lines changed
Lines changed: 324 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,324 @@
1+
---
2+
source-updated-at: 2025-05-19T22:31:51.000Z
3+
translation-updated-at: 2025-05-20T22:28:11.605Z
4+
title: error.js
5+
description: 关于 error.js 特殊文件的 API 参考文档。
6+
related:
7+
title: 了解更多错误处理相关内容
8+
links:
9+
- app/building-your-your-application/routing/error-handling
10+
---
11+
12+
**error** 文件允许您处理意外的运行时错误并显示回退 UI。
13+
14+
<Image
15+
alt="error.js 特殊文件"
16+
srcLight="/docs/light/error-special-file.png"
17+
srcDark="/docs/dark/error-special-file.png"
18+
width="1600"
19+
height="606"
20+
/>
21+
22+
```tsx filename="app/dashboard/error.tsx" switcher
23+
'use client' // 错误边界必须是客户端组件
24+
25+
import { useEffect } from 'react'
26+
27+
export default function Error({
28+
error,
29+
reset,
30+
}: {
31+
error: Error & { digest?: string }
32+
reset: () => void
33+
}) {
34+
useEffect(() => {
35+
// 将错误记录到错误报告服务
36+
console.error(error)
37+
}, [error])
38+
39+
return (
40+
<div>
41+
<h2>Something went wrong!</h2>
42+
<button
43+
onClick={
44+
// 尝试通过重新渲染该分段来恢复
45+
() => reset()
46+
}
47+
>
48+
Try again
49+
</button>
50+
</div>
51+
)
52+
}
53+
```
54+
55+
```jsx filename="app/dashboard/error.js" switcher
56+
'use client' // 错误边界必须是客户端组件
57+
58+
import { useEffect } from 'react'
59+
60+
export default function Error({ error, reset }) {
61+
useEffect(() => {
62+
// 将错误记录到错误报告服务
63+
console.error(error)
64+
}, [error])
65+
66+
return (
67+
<div>
68+
<h2>Something went wrong!</h2>
69+
<button
70+
onClick={
71+
// 尝试通过重新渲染该分段来恢复
72+
() => reset()
73+
}
74+
>
75+
Try again
76+
</button>
77+
</div>
78+
)
79+
}
80+
```
81+
82+
`error.js` 将路由分段及其嵌套子节点包裹在一个 [React 错误边界](https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary)中。当边界内抛出错误时,`error` 组件会作为回退 UI 显示。
83+
84+
<Image
85+
alt="error.js 工作原理"
86+
srcLight="/docs/light/error-overview.png"
87+
srcDark="/docs/dark/error-overview.png"
88+
width="1600"
89+
height="903"
90+
/>
91+
92+
> **须知**:
93+
>
94+
> - 使用 [React DevTools](https://react.dev/learn/react-developer-tools) 可以切换错误边界来测试错误状态。
95+
> - 如果希望错误冒泡到父级错误边界,可以在渲染 `error` 组件时使用 `throw`
96+
97+
## 参考
98+
99+
### Props
100+
101+
#### `error`
102+
103+
传递给 `error.js` 客户端组件的 [`Error`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error) 对象实例。
104+
105+
> **须知:** 在开发环境中,传递给客户端的 `Error` 对象会被序列化,并包含原始错误的 `message` 以便调试。但在生产环境中,**此行为会有所不同**,以避免将错误中可能包含的敏感信息泄露给客户端。
106+
107+
#### `error.message`
108+
109+
- 从客户端组件转发的错误会显示原始 `Error` 消息。
110+
- 从服务端组件转发的错误会显示带有标识符的通用消息。这是为了防止泄露敏感信息。您可以使用 `errors.digest` 下的标识符来匹配对应的服务端日志。
111+
112+
#### `error.digest`
113+
114+
自动生成的错误哈希值。可用于匹配服务端日志中的对应错误。
115+
116+
#### `reset`
117+
118+
有时错误的起因可能是暂时的。在这些情况下,重试可能会解决问题。
119+
120+
错误组件可以使用 `reset()` 函数提示用户尝试从错误中恢复。执行该函数时,会尝试重新渲染错误边界的内容。如果成功,回退的错误组件将被重新渲染的结果替换。
121+
122+
```tsx filename="app/dashboard/error.tsx" switcher
123+
'use client' // 错误边界必须是客户端组件
124+
125+
export default function Error({
126+
error,
127+
reset,
128+
}: {
129+
error: Error & { digest?: string }
130+
reset: () => void
131+
}) {
132+
return (
133+
<div>
134+
<h2>Something went wrong!</h2>
135+
<button onClick={() => reset()}>Try again</button>
136+
</div>
137+
)
138+
}
139+
```
140+
141+
```jsx filename="app/dashboard/error.js" switcher
142+
'use client' // 错误边界必须是客户端组件
143+
144+
export default function Error({ error, reset }) {
145+
return (
146+
<div>
147+
<h2>Something went wrong!</h2>
148+
<button onClick={() => reset()}>Try again</button>
149+
</div>
150+
)
151+
}
152+
```
153+
154+
## 示例
155+
156+
### 全局错误
157+
158+
虽然不太常见,但您可以使用位于根应用目录中的 `global-error.js` 来处理根布局或模板中的错误,即使在使用[国际化](/docs/app/building-your-application/routing/internationalization)时也是如此。全局错误 UI 必须定义自己的 `<html>``<body>` 标签。此文件在激活时会替换根布局或模板。
159+
160+
```tsx filename="app/global-error.tsx" switcher
161+
'use client' // 错误边界必须是客户端组件
162+
163+
export default function GlobalError({
164+
error,
165+
reset,
166+
}: {
167+
error: Error & { digest?: string }
168+
reset: () => void
169+
}) {
170+
return (
171+
// global-error 必须包含 html 和 body 标签
172+
<html>
173+
<body>
174+
<h2>Something went wrong!</h2>
175+
<button onClick={() => reset()}>Try again</button>
176+
</body>
177+
</html>
178+
)
179+
}
180+
```
181+
182+
```jsx filename="app/global-error.js" switcher
183+
'use client' // 错误边界必须是客户端组件
184+
185+
export default function GlobalError({ error, reset }) {
186+
return (
187+
// global-error 必须包含 html 和 body 标签
188+
<html>
189+
<body>
190+
<h2>Something went wrong!</h2>
191+
<button onClick={() => reset()}>Try again</button>
192+
</body>
193+
</html>
194+
)
195+
}
196+
```
197+
198+
### 使用自定义错误边界优雅恢复错误
199+
200+
当客户端渲染失败时,显示最后已知的服务端渲染 UI 可以提供更好的用户体验。
201+
202+
`GracefullyDegradingErrorBoundary` 是一个自定义错误边界的示例,它捕获并保留错误发生前的当前 HTML。如果发生渲染错误,它会重新渲染捕获的 HTML 并显示一个持久通知栏来通知用户。
203+
204+
```tsx filename="app/dashboard/error.tsx" switcher
205+
'use client'
206+
207+
import React, { Component, ErrorInfo, ReactNode } from 'react'
208+
209+
interface ErrorBoundaryProps {
210+
children: ReactNode
211+
onError?: (error: Error, errorInfo: ErrorInfo) => void
212+
}
213+
214+
interface ErrorBoundaryState {
215+
hasError: boolean
216+
}
217+
218+
export class GracefullyDegradingErrorBoundary extends Component<
219+
ErrorBoundaryProps,
220+
ErrorBoundaryState
221+
> {
222+
private contentRef: React.RefObject<HTMLDivElement>
223+
224+
constructor(props: ErrorBoundaryProps) {
225+
super(props)
226+
this.state = { hasError: false }
227+
this.contentRef = React.createRef()
228+
}
229+
230+
static getDerivedStateFromError(_: Error): ErrorBoundaryState {
231+
return { hasError: true }
232+
}
233+
234+
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
235+
if (this.props.onError) {
236+
this.props.onError(error, errorInfo)
237+
}
238+
}
239+
240+
render() {
241+
if (this.state.hasError) {
242+
// 渲染当前 HTML 内容而不进行水合
243+
return (
244+
<>
245+
<div
246+
ref={this.contentRef}
247+
suppressHydrationWarning
248+
dangerouslySetInnerHTML={{
249+
__html: this.contentRef.current?.innerHTML || '',
250+
}}
251+
/>
252+
<div className="fixed bottom-0 left-0 right-0 bg-red-600 text-white py-4 px-6 text-center">
253+
<p className="font-semibold">
254+
An error occurred during page rendering
255+
</p>
256+
</div>
257+
</>
258+
)
259+
}
260+
261+
return <div ref={this.contentRef}>{this.props.children}</div>
262+
}
263+
}
264+
265+
export default GracefullyDegradingErrorBoundary
266+
```
267+
268+
```jsx filename="app/dashboard/error.js" switcher
269+
'use client'
270+
271+
import React, { Component, createRef } from 'react'
272+
273+
class GracefullyDegradingErrorBoundary extends Component {
274+
constructor(props) {
275+
super(props)
276+
this.state = { hasError: false }
277+
this.contentRef = createRef()
278+
}
279+
280+
static getDerivedStateFromError(_) {
281+
return { hasError: true }
282+
}
283+
284+
componentDidCatch(error, errorInfo) {
285+
if (this.props.onError) {
286+
this.props.onError(error, errorInfo)
287+
}
288+
}
289+
290+
render() {
291+
if (this.state.hasError) {
292+
// 渲染当前 HTML 内容而不进行水合
293+
return (
294+
<>
295+
<div
296+
ref={this.contentRef}
297+
suppressHydrationWarning
298+
dangerouslySetInnerHTML={{
299+
__html: this.contentRef.current?.innerHTML || '',
300+
}}
301+
/>
302+
<div className="fixed bottom-0 left-0 right-0 bg-red-600 text-white py-4 px-6 text-center">
303+
<p className="font-semibold">
304+
An error occurred during page rendering
305+
</p>
306+
</div>
307+
</>
308+
)
309+
}
310+
311+
return <div ref={this.contentRef}>{this.props.children}</div>
312+
}
313+
}
314+
315+
export default GracefullyDegradingErrorBoundary
316+
```
317+
318+
## 版本历史
319+
320+
| 版本 | 变更 |
321+
| ---------- | ---------------------------------------- |
322+
| `v15.2.0` | 在开发环境中也显示 `global-error`。 |
323+
| `v13.1.0` | 引入 `global-error`。 |
324+
| `v13.0.0` | 引入 `error`。 |
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
---
2+
source-updated-at: 2025-05-16T04:52:11.000Z
3+
translation-updated-at: 2025-05-20T22:27:04.635Z
4+
title: forbidden.js
5+
description: 关于 forbidden.js 特殊文件的 API 参考文档。
6+
related:
7+
links:
8+
- app/api-reference/functions/forbidden
9+
version: experimental
10+
---
11+
12+
**forbidden** 文件用于在身份验证期间调用 [`forbidden`](/docs/app/api-reference/functions/forbidden) 函数时渲染 UI。除了允许您自定义 UI 外,Next.js 还会返回 `403` 状态码。
13+
14+
```tsx filename="app/forbidden.tsx" switcher
15+
import Link from 'next/link'
16+
17+
export default function Forbidden() {
18+
return (
19+
<div>
20+
<h2>Forbidden</h2>
21+
<p>You are not authorized to access this resource.</p>
22+
<Link href="/">Return Home</Link>
23+
</div>
24+
)
25+
}
26+
```
27+
28+
```jsx filename="app/forbidden.jsx" switcher
29+
import Link from 'next/link'
30+
31+
export default function Forbidden() {
32+
return (
33+
<div>
34+
<h2>Forbidden</h2>
35+
<p>You are not authorized to access this resource.</p>
36+
<Link href="/">Return Home</Link>
37+
</div>
38+
)
39+
}
40+
```
41+
42+
## 参考文档
43+
44+
### Props
45+
46+
`forbidden.js` 组件不接受任何 props。
47+
48+
## 版本历史
49+
50+
| 版本 | 变更 |
51+
| ---------- | ------------------------ |
52+
| `v15.1.0` | 引入 `forbidden.js` 功能 |
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
source-updated-at: 2025-05-16T04:52:11.000Z
3+
translation-updated-at: 2025-05-20T22:26:49.747Z
4+
title: 文件系统约定
5+
description: Next.js 文件系统约定的 API 参考文档。
6+
---

0 commit comments

Comments
 (0)