Next.js 路由錯誤處理:新手指南

2025-03-21 18:56 更新

在 Next.js 應用程序中,錯誤可分為兩類:預期錯誤和未捕獲異常。本頁將指導你如何處理這些錯誤。

處理預期錯誤

預期錯誤是指在應用程序正常運行過程中可能發(fā)生的情況,例如服務器端表單驗證錯誤或請求失敗。這些錯誤應顯式處理并返回給客戶端。

在服務器操作中處理預期錯誤

使用 useActionState 鉤子來管理服務器操作的狀態(tài),包括處理錯誤。這種方法避免了對預期錯誤使用 try/catch 塊,而是將錯誤建模為返回值,而不是拋出異常。

'use server'


import { redirect } from 'next/navigation'


export async function createUser(prevState: any, formData: FormData) {
  const res = await fetch('https://...')
  const json = await res.json()


  if (!res.ok) {
    return { message: '請輸入有效的郵箱' }
  }


  redirect('/dashboard')
}

然后,你可以將操作傳遞給 useActionState 鉤子,并使用返回的 state 顯示錯誤消息。

'use client'


import { useActionState } from 'react'
import { createUser } from '@/app/actions'


const initialState = {
  message: '',
}


export function Signup() {
  const [state, formAction, pending] = useActionState(createUser, initialState)


  return (
    <form action={formAction}>
      <label htmlFor="email">郵箱</label>
      <input type="text" id="email" name="email" required />
      {/* ... */}
      <p aria-live="polite">{state?.message}</p>
      <button disabled={pending}>注冊</button>
    </form>
  )
}

你也可以使用返回的狀態(tài)從客戶端組件顯示一個提示消息。

在服務器組件中處理預期錯誤

在服務器組件中獲取數據時,可以使用響應來條件渲染錯誤消息或 redirect。

export default async function Page() {
  const res = await fetch(`https://...`)
  const data = await res.json()


  if (!res.ok) {
    return '發(fā)生錯誤'
  }


  return '...'
}

處理未捕獲異常

未捕獲異常是意料之外的錯誤,表示在應用程序的正常流程中不應發(fā)生的錯誤。這些錯誤應通過拋出錯誤來處理,然后由錯誤邊界捕獲。

使用錯誤邊界

Next.js 使用錯誤邊界來處理未捕獲異常。錯誤邊界捕獲子組件中的錯誤,并顯示備用 UI 而不是崩潰的組件樹。

通過在路由段中添加 error.tsx 文件并導出 React 組件來創(chuàng)建錯誤邊界:

'use client' // 錯誤邊界必須是客戶端組件


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 組件時拋出錯誤。

在嵌套路由中處理錯誤

錯誤將冒泡到最近的父級錯誤邊界。這允許在路由層次結構的不同級別放置 error.tsx 文件,從而實現細粒度的錯誤處理。

Next.js 在嵌套路由中處理錯誤

處理全局錯誤

雖然不常見,但你可以在根布局中使用 app/global-error.js 文件處理錯誤,即使在使用國際化的情況下。全局錯誤 UI 必須定義自己的 <html><body> 標簽,因為它在活動時會替換根布局或模板。

'use client' // 錯誤邊界必須是客戶端組件


export default function GlobalError({
  error,
  reset,
}: {
  error: Error & { digest?: string }
  reset: () => void
}) {
  return (
    // 全局錯誤必須包含 html 和 body 標簽
    <html>
      <body>
        <h2>出錯了!</h2>
        <button onClick={() => reset()}>重試</button>
      </body>
    </html>
  )
}
以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號