Next.js 路由錯(cuò)誤處理:新手指南

2025-03-21 18:56 更新

在 Next.js 應(yīng)用程序中,錯(cuò)誤可分為兩類:預(yù)期錯(cuò)誤和未捕獲異常。本頁(yè)將指導(dǎo)你如何處理這些錯(cuò)誤。

處理預(yù)期錯(cuò)誤

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

在服務(wù)器操作中處理預(yù)期錯(cuò)誤

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

'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: '請(qǐng)輸入有效的郵箱' }
  }


  redirect('/dashboard')
}

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

'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}>注冊(cè)</button>
    </form>
  )
}

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

在服務(wù)器組件中處理預(yù)期錯(cuò)誤

在服務(wù)器組件中獲取數(shù)據(jù)時(shí),可以使用響應(yīng)來(lái)?xiàng)l件渲染錯(cuò)誤消息或 redirect

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


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


  return '...'
}

處理未捕獲異常

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

使用錯(cuò)誤邊界

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

通過(guò)在路由段中添加 error.tsx 文件并導(dǎo)出 React 組件來(lái)創(chuàng)建錯(cuò)誤邊界:

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


import { useEffect } from 'react'


export default function Error({
  error,
  reset,
}: {
  error: Error & { digest?: string }
  reset: () => void
}) {
  useEffect(() => {
    // 將錯(cuò)誤記錄到錯(cuò)誤報(bào)告服務(wù)
    console.error(error)
  }, [error])


  return (
    <div>
      <h2>出錯(cuò)了!</h2>
      <button
        onClick={
          // 嘗試通過(guò)重新渲染段來(lái)恢復(fù)
          () => reset()
        }
      >
        重試
      </button>
    </div>
  )
}

如果你想讓錯(cuò)誤冒泡到父級(jí)錯(cuò)誤邊界,可以在渲染 error 組件時(shí)拋出錯(cuò)誤。

在嵌套路由中處理錯(cuò)誤

錯(cuò)誤將冒泡到最近的父級(jí)錯(cuò)誤邊界。這允許在路由層次結(jié)構(gòu)的不同級(jí)別放置 error.tsx 文件,從而實(shí)現(xiàn)細(xì)粒度的錯(cuò)誤處理。

Next.js 在嵌套路由中處理錯(cuò)誤

處理全局錯(cuò)誤

雖然不常見(jiàn),但你可以在根布局中使用 app/global-error.js 文件處理錯(cuò)誤,即使在使用國(guó)際化的情況下。全局錯(cuò)誤 UI 必須定義自己的 <html><body> 標(biāo)簽,因?yàn)樗诨顒?dòng)時(shí)會(huì)替換根布局或模板。

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


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

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)