Next.js 載入中與錯誤處理
在現代網頁應用中,使用者體驗 (UX) 的關鍵在於「即時回饋」。當使用者點擊連結後,系統不應該毫無反應。Next.js 透過內建的 loading.tsx 和 error.tsx 檔案慣例,讓你能輕鬆處理這些狀態。
載入中狀態 (Loading UI)
loading.tsx 檔案利用了 React 的 Suspense 機制,當該路由的內容(Server Components)正在擷取數據時,會自動顯示此 UI。
為什麼這很重要?
- 即時回饋:導航時會立即切換到 Loading 畫面。
- 共享 Layout:當 Loading 顯示時,導航欄等共享 UI 依然是可互動的。
實作範例:
只需在路由資料夾下建立 loading.tsx:
// app/dashboard/loading.tsx
export default function Loading() {
// 你可以使用 Tailwind CSS 畫一個簡單的 Skeleton 畫面
return (
<div className="flex items-center justify-center min-h-[200px]">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-500"></div>
<p className="ml-4 text-gray-500 font-medium">資料載入中,請稍候...</p>
</div>
);
}
錯誤處理 (Error Handling)
error.tsx 檔案利用了 Error Boundary 機制。它會攔截子組件中發生的非預期運行錯誤,並顯示一個備用的 UI,而不是讓整個網站崩潰 (Crash)。
實作範例:
// app/dashboard/error.tsx
'use client'; // Error Components 必須是 Client Components
import { useEffect } from 'react';
export default function Error({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
useEffect(() => {
// 你可以將錯誤記錄到 Sentry 等監控服務
console.error(error);
}, [error]);
return (
<div className="p-8 text-center bg-red-50 rounded-lg border border-red-200">
<h2 className="text-xl font-bold text-red-600 mb-2">發生了非預期錯誤!</h2>
<p className="text-red-500 mb-4">{error.message || '請聯繫管理員。'}</p>
<button
onClick={() => reset()} // 嘗試重新渲染該路由
className="px-6 py-2 bg-red-600 text-white font-semibold rounded-md hover:bg-red-700 transition"
>
嘗試重新載入
</button>
</div>
);
}
error.tsx 只會捕獲該分段及其子分段的錯誤。如果 layout.tsx 中發生錯誤,則由父級的 error.tsx 捕獲。處理 404 (Not Found)
當某個路由不存在,或是你在程式中主動確認該資源不存在時,可以使用 not-found.tsx。
主動呼叫範例:
// app/users/[id]/page.tsx
import { notFound } from 'next/navigation';
export default async function UserProfile({ params }: { params: { id: string } }) {
const user = await fetchUser(params.id);
if (!user) {
// 當資料庫查無此人時,主動觸發 404
notFound();
}
return <div>Hello, {user.name}</div>;
}
小結
透過這些內建檔案,你不需要手動控制每個頁面的 isLoading 或 error 狀態:
loading.tsx:負責數據加載期間的視覺。error.tsx:負責發生崩潰時的復原。not-found.tsx:負責處理不存在的資源。
這套機制讓你的核心程式碼更乾淨,同時確保了極高的穩定性。