Apr 19, 2025
Khi Website Của Bạn Biến Thành Màn Hình Trắng: Cách Xử Lý Lỗi Hiệu Quả Trong React.js
Phineas
@Phineas

Hãy tưởng tượng bạn vừa hoàn thành sản phẩm quan trọng nhất của mình. Bạn nhấn nút deploy, mở trình duyệt và... một màn hình trắng toát hiện ra.
Không có thông báo lỗi. Không có cảnh báo. Chỉ là một khoảng trống vô tận.
Bạn mở DevTools và thấy một dòng chữ đỏ chói chặng hạn:
Uncaught TypeError:
Tim bạn đập mạnh. Người dùng đang truy cập trang web của bạn ngay lúc này. Bạn làm gì để khắc phục?
Trong bài viết này, mình sẽ giới thiệu 2 cách xử lý lỗi hiệu quả trong React.js mà mình hay dùng, ứng dụng của bạn không bao giờ rơi vào tình trạng “màn hình trắng” đầy ám ảnh.
1. Xử lý lỗi UI với Error Boundary trong React
React cung cấp cơ chế Error Boundary để ngăn chặn lỗi trong component làm sập toàn bộ ứng dụng. Chúng ta có thể tạo một Error Boundary đơn giản như sau:
import React, { ReactNode } from "react";
interface ErrorBoundaryProps {
children: ReactNode;
}
interface ErrorBoundaryState {
hasError: boolean;
}
class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {
state: ErrorBoundaryState = { hasError: false };
static getDerivedStateFromError() {
return { hasError: true };
}
componentDidCatch(error: Error, info: React.ErrorInfo) {
console.error("Caught an error:", error, info);
}
render() {
if (this.state.hasError) {
return <h1>Oops! Đã xảy ra lỗi.</h1>;
}
return this.props.children;
}
}
export default ErrorBoundary;
Sau đó chúng ta có thể bọc nó ở ngoài App:
import ErrorBoundary from "./ErrorBoundary";
import App from "./App";
const Root = () => (
<ErrorBoundary>
<App />
</ErrorBoundary>
);
export default Root;
Lúc này, khi một trong số component con bị crash, web chúng ta sẽ hiển thị lỗi như này thay vì màn hình trắng:

Note: Chúng ta cũng có thể custom thêm để hiển thị message khác, hoặc bọc <ErrorBoundary> ở các component con, để fallback error cũng được
<ErrorBoundary fallback={<p>Something went wrong</p>}>
<Profile />
</ErrorBoundary>
2. Tạo hệ thống quản lý lỗi trong API với Axios Interceptor
Việc gọi API luôn luôn tiềm ẩn lỗi như mất kết nối, lỗi server, hoặc lỗi xác thực. Do đó, chúng ta cần một hệ thống quản lý lỗi rõ ràng.
Trước tiên, hãy tạo một lớp lỗi chung để quản lý tất cả các loại lỗi trong ứng dụng:
export class ApplicationError extends Error {
constructor(message: string) {
super(message);
this.name = 'ApplicationError';
Object.setPrototypeOf(this, new.target.prototype);
}
}
Sau đó, mở rộng lớp này để tạo ra các lỗi cụ thể:
export class ApiError extends ApplicationError {
constructor(message: string) {
super(message);
this.name = 'ApiError';
}
}
export class UnauthorizedError extends ApplicationError {
constructor(message: string) {
super(message);
this.name = 'UnauthorizedError';
}
}
export class ForbiddenError extends ApplicationError {
constructor(message: string) {
super(message);
this.name = 'ForbiddenError';
}
}
Việc chia nhỏ lỗi như trên sẽ giúp chúng ta dễ dàng xử lý từng loại lỗi một cách cụ thể.
Tiếp theo, chúng ta sử dụng interceptor của Axios để bắt và xử lý lỗi API:
import axios from "axios";
import { UnauthorizedError, ForbiddenError, ApiError } from "./errors";
axios.interceptors.response.use(
(response) => response,
async (error) => {
if (!axios.isAxiosError(error)) {
throw new ApiError("Unknown error");
}
if (error.response?.status === 401) {
throw new UnauthorizedError("Bạn cần đăng nhập");
}
if (error.response?.status === 403) {
throw new ForbiddenError("Bạn không có quyền truy cập");
}
throw new ApiError("Lỗi từ API");
}
);
🔥 Cách hoạt động của interceptor:
- Nếu request thành công, trả về
response
như bình thường. - Nếu lỗi xảy ra, kiểm tra mã lỗi:
- 401 Unauthorized: Người dùng cần đăng nhập
- 403 Forbidden: Người dùng không có quyền truy cập
- Các lỗi khác: Trả về lỗi API chung
Tiếp theo, xử lý lỗi API trong React Component. Ví dụ:
const fetchData = async () => {
try {
const response = await axios.get("/api/data");
console.log("Data:", response.data);
} catch (error) {
if (error instanceof UnauthorizedError) {
alert("Bạn cần đăng nhập để tiếp tục");
} else if (error instanceof ForbiddenError) {
alert("Bạn không có quyền truy cập");
} else {
alert("Đã có lỗi xảy ra, vui lòng thử lại!");
}
}
};
Dễ hiểu mà, đúng không? Nhờ việc phân loại lỗi rõ ràng, chúng ta có thể hiển thị thông báo phù hợp với từng trường hợp, giúp người dùng hiểu rõ vấn đề và có hướng giải quyết.
3. Tổng kết
Việc code để xảy ra lỗi là điều bình thường, nhưng hãy cố gắng cover các case cơ bản có thể xảy ra để tránh trang bị crash, ví dụ như kiểm tra type, kiểm tra giá trị trước khi render,…
Ngoài ra chúng ta cũng có thể dùng các công cụ thứ 3 như sentry để theo dõi ứng dụng, sớm kịp thời phát hiện lỗi để fix sớm.
Ok. Vậy tổng kết như sau:
✅ Sử dụng Error Boundary để ngăn lỗi UI làm crash toàn bộ ứng dụng.
✅ Tạo hệ thống quản lý lỗi API bằng cách chia nhỏ lỗi thành các class riêng.
✅ Sử dụng Axios Interceptor để tự động xử lý lỗi API.
✅ Hiển thị thông báo lỗi thân thiện cho người dùng.
Với những kỹ thuật trên, bạn có thể xây dựng một ứng dụng React ổn định hơn, giúp người dùng có trải nghiệm mượt mà ngay cả khi có lỗi xảy ra. Hãy áp dụng ngay và chia sẻ kết quả của bạn nhé! 🚀