Mục lục

Next.js Error System: Bí mật đằng sau error.tsx

Cơ chế hoạt động thực sự của error.tsx: Next.js tự động bọc component của bạn bằng Error Boundary như thế nào? Cách xử lý Nested Errors và Recovery.

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:

tsx:
<Layout>
  {/* 👇 Next.js tự động chèn Class ErrorBoundary bao quanh page */}
  <ErrorBoundary fallback={<ErrorComponent />}>
    <Page />
  </ErrorBoundary>
</Layout>
  • Page: Là page.tsx của bạn.
  • ErrorComponent: Là error.tsx của bạn.
  • Layout: Nằm bên ngoài Error Boundary. (Điều này cực kỳ quan trọng!).

👉 Hệ quả:

  1. Nếu Page lỗi -> ErrorComponent hiện ra -> Layout (Sidebar/Header) VẪN GIỮ NGUYÊN.
  2. error.tsx phải"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

tsx:
// 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:

Code:
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.tsx sẽ được bắt bởi dashboard/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à:

  1. Tạo file error.tsx.
  2. Thêm "use client".
  3. Design UI lỗi đẹp mắt và thêm nút reset.
Quảng cáo
mdhorizontal