如何在 Next.js 應用程序中處理錯誤

2025-03-21 10:12 更新

如何處理錯誤

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

處理預期錯誤

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

服務器操作

你可以使用 useActionState 鉤子來管理服務器函數(shù)的狀態(tài)并處理預期錯誤。對于預期錯誤,避免使用 try/catch 塊。相反,可以將預期錯誤建模為返回值,而不是拋出異常。

  1. 'use server'
  2. export async function createPost(prevState: any, formData: FormData) {
  3. const title = formData.get('title')
  4. const content = formData.get('content')
  5. const res = await fetch('https://api.vercel.app/posts', {
  6. method: 'POST',
  7. body: { title, content },
  8. })
  9. const json = await res.json()
  10. if (!res.ok) {
  11. return { message: 'Failed to create post' }
  12. }
  13. }

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

  1. 'use client'
  2. import { useActionState } from 'react'
  3. import { createPost } from '@/app/actions'
  4. const initialState = {
  5. message: '',
  6. }
  7. export function Form() {
  8. const [state, formAction, pending] = useActionState(createPost, initialState)
  9. return (
  10. <form action={formAction}>
  11. <label htmlFor="title">標題</label>
  12. <input type="text" id="title" name="title" required />
  13. <label htmlFor="content">內(nèi)容</label>
  14. <textarea id="content" name="content" required />
  15. {state?.message && <p aria-live="polite">{state.message}</p>}
  16. <button disabled={pending}>創(chuàng)建帖子</button>
  17. </form>
  18. )
  19. }

服務器組件

在服務器組件中獲取數(shù)據(jù)時,可以使用響應來條件渲染錯誤消息或 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. }

未找到

你可以在路由段中調(diào)用 notFound 函數(shù),并使用 not-found.js 文件顯示 404 UI。

  1. import { getPostBySlug } from '@/lib/posts'
  2. export default async function Page({ params }: { params: { slug: string } }) {
  3. const { slug } = await params
  4. const post = getPostBySlug(slug)
  5. if (!post) {
  6. notFound()
  7. }
  8. return <div>{post.title}</div>
  9. }

  1. export default function NotFound() {
  2. return <div>404 - 未找到頁面</div>
  3. }

處理未捕獲異常

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

嵌套錯誤邊界

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

通過在路由段中添加 error.js 文件并導出 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.tsx 文件,從而實現(xiàn)細粒度的錯誤處理。

全局錯誤

雖然不常見,但你可以在根布局中使用 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. }

API 參考

閱讀 API 參考 ,了解有關本頁中提到的功能的更多信息。

  • 重定向 重定向函數(shù)的 API 參考。

  • error.js error.js 特殊文件的 API 參考。

  • 未找到 notFound 函數(shù)的 API 參考。

  • not-found.js not-found.js 文件的 API 參考。
以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號