Trong JavaScript thuần, nếu một dòng code lỗi -> Script dừng lại. Trong React, nếu một Component lỗi -> Toàn bộ cây DOM bị gỡ bỏ (Trang trắng tinh "White Screen of Death"). Error Boundary là cách để cô lập vùng lỗi đó.
1. Hiện trạng Function Component (2025)
Câu hỏi: "Tôi ghét Class Component. Tôi có thể viết Error Boundary bằng Function/Hook không?"
Trả lời: Về mặt kỹ thuật là KHÔNG.
Tính đến React 19, các lifecycle getDerivedStateFromError và componentDidCatch chỉ tồn tại trong Class Component. Chưa có Hook tương đương.
NHƯNG:
- Next.js App Router: File
error.tsxLÀ Function Component. (Next.js đã wrap Class ngầm bên dưới cho bạn). - External Library: Thư viện
react-error-boundarygiúp bạn dùng Error Boundary theo phong cách Functional Programming 100%.
2. Cách dùng react-error-boundary (Khuyên dùng)
Đây là chuẩn mực hiện đại. Bạn không bao giờ phải viết class nữa.
import { ErrorBoundary } from "react-error-boundary";
// 1. Fallback Component (Là Function Component bình thường)
// Nhận props { error, resetErrorBoundary }
function ErrorFallback({ error, resetErrorBoundary }) {
return (
<div role="alert" className="p-4 bg-red-100 text-red-900 rounded">
<p className="font-bold">Oops! Có lỗi xảy ra:</p>
<pre className="text-sm">{error.message}</pre>
{/* Nút Reset giúp user thử lại mà không cần F5 trang */}
<button
onClick={resetErrorBoundary}
className="mt-2 px-4 py-2 bg-red-600 text-white rounded"
>
Thử lại
</button>
</div>
);
}
// 2. Wrap Component
function App() {
return (
// onReset: Nơi bạn reset state của app về ban đầu để component con render lại sạch sẽ
<ErrorBoundary
FallbackComponent={ErrorFallback}
onReset={() => {
// Ví dụ: Reset form, clear cache
console.log("Resetting app state...");
}}
>
<ProductList />
</ErrorBoundary>
);
}3. Bắt lỗi trong Event Handler (useErrorBoundary)
Lỗi trong onClick (Event Handler) KHÔNG làm crash React Render, nên Error Boundary mặc định không bắt được.
Muốn bắt lỗi này (để hiện UI lỗi đồng bộ), bạn phải dùng React 19 useActionState hoặc thư viện useErrorBoundary.
import { useErrorBoundary } from "react-error-boundary";
function LoginButton() {
const { showBoundary } = useErrorBoundary();
const handleClick = async () => {
try {
await loginAPI();
} catch (error) {
// 🚀 Trick: Ném lỗi vào vòng Render để Error Boundary trên cao bắt được
showBoundary(error);
}
};
return <button onClick={handleClick}>Login</button>;
}4. Class Component (Dành cho ai tò mò)
Nếu bạn không muốn cài thư viện, bạn phải tự viết Class này (Copy-paste cái này dùng cho cả dự án).
class ErrorBoundary extends React.Component {
state = { hasError: false };
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, info) {
// Gửi log lỗi lên Server/Sentry
logErrorToService(error, info.componentStack);
}
render() {
if (this.state.hasError) {
return this.props.fallback;
}
return this.props.children;
}
}Kết luận
- Nếu dùng Next.js App Router -> Dùng
error.tsx(Function Component). - Nếu dùng React thường (Vite) -> Dùng
react-error-boundary. - Quên Class Component đi (trừ khi bạn đang maintain code cũ 5 năm trước).