Bạn thắc mắc tại sao Next.js lại dùng error.tsx (Function Component) trong khi React chỉ hỗ trợ Class cho Error Boundary?
Câu trả lời nằm ở "Under the hood".
1. Cơ chế hoạt động (Behind the scenes)
Khi bạn định nghĩa 3 file: layout.tsx, page.tsx, và error.tsx.
Next.js sẽ compile chúng thành một cấu trúc cây component lồng nhau như sau:
<Layout>
{/* 👇 Next.js tự động chèn Class ErrorBoundary bao quanh page */}
<ErrorBoundary fallback={<ErrorComponent />}>
<Page />
</ErrorBoundary>
</Layout>Page: Làpage.tsxcủa bạn.ErrorComponent: Làerror.tsxcủa bạn.Layout: Nằm bên ngoài Error Boundary. (Điều này cực kỳ quan trọng!).
👉 Hệ quả:
- Nếu
Pagelỗi ->ErrorComponenthiện ra ->Layout(Sidebar/Header) VẪN GIỮ NGUYÊN. - Và
error.tsxphải là"use client"vì Error Boundary (phần fallback) luôn chạy ở phía client để tương tác (nút Reset).
2. Cách triển khai error.tsx chuẩn
// app/dashboard/error.tsx
'use client'; // 👈 Bắt buộc
import { useEffect } from 'react';
export default function Error({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
// 1. Log lỗi ngay khi component mount
useEffect(() => {
// Gửi log lên Sentry, Datadog...
console.error("Dashboard Error:", error);
}, [error]);
return (
<div className="flex flex-col items-center p-6 bg-red-50 border border-red-200 rounded-lg">
<h2 className="text-xl font-bold text-red-700">Đã có lỗi xảy ra!</h2>
<p className="text-gray-600 mb-4">{error.message}</p>
{/* 2. Nút Recovery Strategy */}
{/* reset() sẽ cố render lại phần Page đang bị lỗi */}
<button
onClick={() => reset()}
className="px-4 py-2 bg-red-600 text-white rounded hover:bg-red-700 transition"
>
Thử lại
</button>
</div>
);
}3. Nested Routes (Lỗi cục bộ)
Giả sử bạn có cấu trúc thư mục:
app/
├── error.tsx (Fallback A)
├── layout.tsx
└── dashboard/
├── error.tsx (Fallback B)
└── page.tsx (Lỗi xảy ra ở đây)Hành vi:
- Lỗi ở
dashboard/page.tsxsẽ được bắt bởidashboard/error.tsx(Fallback B). -> Gần nhất thắng. - Fallback A sẽ không được kích hoạt.
- User vẫn thấy Layout chung của app, và chỉ phần Dashboard bị thay thế bởi Fallback B.
Tuy nhiên, nếu lỗi xảy ra ở app/layout.tsx (Layout cha), thì KHÔNG CÓ error.tsx nào bên trong bắt được (vì Layout nằm ngoài Boundary con). Bạn phải dùng global-error.tsx.
Kết luận
Next.js đã "abstract" (trừu tượng hóa) khái niệm Error Boundary phức tạp thành file error.tsx đơn giản.
Nhiệm vụ của bạn chỉ là:
- Tạo file
error.tsx. - Thêm
"use client". - Design UI lỗi đẹp mắt và thêm nút
reset.