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

2025-03-21 18:56 更新

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

處理預期錯誤

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

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

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

  1. 'use server'
  2. import { redirect } from 'next/navigation'
  3. export async function createUser(prevState: any, formData: FormData) {
  4. const res = await fetch('https://...')
  5. const json = await res.json()
  6. if (!res.ok) {
  7. return { message: '請輸入有效的郵箱' }
  8. }
  9. redirect('/dashboard')
  10. }

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

  1. 'use client'
  2. import { useActionState } from 'react'
  3. import { createUser } from '@/app/actions'
  4. const initialState = {
  5. message: '',
  6. }
  7. export function Signup() {
  8. const [state, formAction, pending] = useActionState(createUser, initialState)
  9. return (
  10. <form action={formAction}>
  11. <label htmlFor="email">郵箱</label>
  12. <input type="text" id="email" name="email" required />
  13. {/* ... */}
  14. <p aria-live="polite">{state?.message}</p>
  15. <button disabled={pending}>注冊</button>
  16. </form>
  17. )
  18. }

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

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

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

  1. export default async function Page() {
  2. const res = await fetch(`https://...`)
  3. const data = await res.json()
  4. if (!res.ok) {
  5. return '發(fā)生錯誤'
  6. }
  7. return '...'
  8. }

處理未捕獲異常

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

使用錯誤邊界

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

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

  1. 'use client' // 錯誤邊界必須是客戶端組件
  2. import { useEffect } from 'react'
  3. export default function Error({
  4. error,
  5. reset,
  6. }: {
  7. error: Error & { digest?: string }
  8. reset: () => void
  9. }) {
  10. useEffect(() => {
  11. // 將錯誤記錄到錯誤報告服務
  12. console.error(error)
  13. }, [error])
  14. return (
  15. <div>
  16. <h2>出錯了!</h2>
  17. <button
  18. onClick={
  19. // 嘗試通過重新渲染段來恢復
  20. () => reset()
  21. }
  22. >
  23. 重試
  24. </button>
  25. </div>
  26. )
  27. }

如果你想讓錯誤冒泡到父級錯誤邊界,可以在渲染 error 組件時拋出錯誤。

在嵌套路由中處理錯誤

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

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

處理全局錯誤

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

  1. 'use client' // 錯誤邊界必須是客戶端組件
  2. export default function GlobalError({
  3. error,
  4. reset,
  5. }: {
  6. error: Error & { digest?: string }
  7. reset: () => void
  8. }) {
  9. return (
  10. // 全局錯誤必須包含 html 和 body 標簽
  11. <html>
  12. <body>
  13. <h2>出錯了!</h2>
  14. <button onClick={() => reset()}>重試</button>
  15. </body>
  16. </html>
  17. )
  18. }
以上內容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號