如何處理錯誤
錯誤可以分為兩類:預期錯誤和未捕獲的例外。本頁面將引導您瞭解如何在您的 Next.js 應用程式中處理這些錯誤。
處理預期錯誤
預期錯誤是指在應用程式正常運作期間可能發生的錯誤,例如來自伺服器端表單驗證或失敗請求的錯誤。這些錯誤應明確處理並傳回用戶端。
伺服器動作
您可以使用useActionState
Hook 來管理伺服器函式的狀態並處理預期錯誤。避免對預期錯誤使用 try
/catch
區塊。相反地,您可以將預期錯誤建模為傳回值,而不是作為拋出的例外。
app/actions.ts
'use server'
export async function createPost(prevState: any, formData: FormData) {
const title = formData.get('title')
const content = formData.get('content')
const res = await fetch('https://api.vercel.app/posts', {
method: 'POST',
body: { title, content },
})
const json = await res.json()
if (!res.ok) {
return { message: 'Failed to create post' }
}
}
然後,您可以將您的動作傳遞給 useActionState
Hook,並使用傳回的 state
來顯示錯誤訊息。
app/ui/form.tsx
'use client'
import { useActionState } from 'react'
import { createPost } from '@/app/actions'
const initialState = {
message: '',
}
export function Form() {
const [state, formAction, pending] = useActionState(createPost, initialState)
return (
<form action={formAction}>
<label htmlFor="title">Title</label>
<input type="text" id="title" name="title" required />
<label htmlFor="content">Content</label>
<textarea id="content" name="content" required />
{state?.message && <p aria-live="polite">{state.message}</p>}
<button disabled={pending}>Create Post</button>
</form>
)
}
伺服器組件
當在伺服器組件內抓取資料時,您可以使用回應來有條件地渲染錯誤訊息或redirect
。
app/page.tsx
export default async function Page() {
const res = await fetch(`https://...`)
const data = await res.json()
if (!res.ok) {
return 'There was an error.'
}
return '...'
}
找不到
您可以在路由區段內呼叫notFound
函式,並使用not-found.js
檔案來顯示 404 UI。
app/blog/[slug]/page.tsx
import { getPostBySlug } from '@/lib/posts'
export default async function Page({ params }: { params: { slug: string } }) {
const post = getPostBySlug((await params).slug)
if (!post) {
notFound()
}
return <div>{post.title}</div>
}
app/blog/[slug]/not-found.tsx
export default function NotFound() {
return <div>404 - Page Not Found</div>
}
處理未捕獲的例外
未捕獲的例外是意外的錯誤,表示在應用程式正常流程中不應發生的錯誤或問題。這些應該透過拋出錯誤來處理,然後將由錯誤邊界捕獲。
巢狀錯誤邊界
Next.js 使用錯誤邊界來處理未捕獲的例外。錯誤邊界捕獲其子組件中的錯誤,並顯示備用 UI,而不是崩潰的組件樹。
透過在路由區段內新增一個error.js
檔案並匯出 React 組件來建立錯誤邊界
app/dashboard/error.tsx
'use client' // Error boundaries 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>
)
}
錯誤將向上冒泡到最近的父錯誤邊界。這允許透過在路由層次結構中的不同層級放置 error.tsx
檔案來進行細緻的錯誤處理。


全域錯誤
雖然較不常見,但即使在使用國際化時,您也可以使用位於根 app 目錄中的global-error.js
檔案來處理根版面配置中的錯誤。全域錯誤 UI 必須定義自己的 <html>
和 <body>
標籤,因為它在啟動時會取代根版面配置或範本。
app/global-error.tsx
'use client' // Error boundaries must be Client Components
export default function GlobalError({
error,
reset,
}: {
error: Error & { digest?: string }
reset: () => void
}) {
return (
// global-error must include html and body tags
<html>
<body>
<h2>Something went wrong!</h2>
<button onClick={() => reset()}>Try again</button>
</body>
</html>
)
}
API 參考
透過閱讀 API 參考,瞭解更多關於本頁面中提及的功能。
這有幫助嗎?