Khi Lỗi Xuất Hiện Ngay Trước Mắt Khách Hàng: Cách Xử Lý Lỗi Hiệu Quả Trong Next.js & React.js
Bạn làm việc tại một startup công nghệ, và hôm nay là ngày quan trọng – sản phẩm mới của bạn vừa chính thức ra mắt. Bạn mở trang web để kiểm tra lần cuối cùng, nhưng ngay giữa màn hình lại xuất hiện thông báo đáng sợ:
"Something went wrong"
Tim bạn đập mạnh. Bạn vội vàng mở console và thấy một lỗi không rõ ràng:
"Unhandled Runtime Error"
Không có thông tin cụ thể, không có cách nào nhanh chóng để xử lý. Khách hàng thì đang truy cập website, và trải nghiệm của họ có thể bị ảnh hưởng nghiêm trọng. Vậy làm sao để ngăn chặn tình huống này? Làm sao để lỗi không chỉ xuất hiện một cách vô nghĩa mà được xử lý gọn gàng, giúp người dùng có trải nghiệm mượt mà hơn?
Bài viết này sẽ hướng dẫn bạn cách xử lý lỗi hiệu quả trong React.js và Next.js, từ UI cho đến API, để đảm bảo ứng dụng của bạn luôn hoạt động ổn đị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:
// ErrorBoundary.tsx
import React from "react";
class ErrorBoundary extends React.Component {
state = { 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;
Khi một component con gặp lỗi, thay vì làm crash toàn bộ ứng dụng, ErrorBoundary
sẽ hiển thị một thông báo thân thiện hơn.
2. Tạo hệ thống quản lý lỗi trong API
Việc gọi API 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ư vậy giúp chúng ta dễ dàng xử lý từng loại lỗi một cách cụ thể.
3. Bắt lỗi API bằng Axios Interceptor
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.
4. Xử lý lỗi API trong React Component
Sau khi đã có interceptor, việc xử lý lỗi trong React component trở nên đơn giản hơn:
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!");
}
}
};
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.
5. Tổng kết
✅ 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/Next.js ổ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é! 🚀