Cách React Query dẹp loạn useEffect và thoát cảnh giật lag

Lý Hữu Trí
Lý Hữu Trí·4 phút đọc·23 tháng 5, 2026

Nhớ lại những ngày đầu học lập trình web, bạn học được cách fetch dữ liệu từ API bằng useEffectuseState. Cảm giác lúc đó khá ngầu và đầy quyền lực đúng không?

Nhưng rồi dự án bành trướng. Bạn phải tự tay quản lý isLoading, isError, fix lỗi gọi API 2 lần do React Strict Mode, rồi đau đầu xử lý cache dữ liệu. Cái component ngày xưa trông nhỏ xinh giờ biến thành một bãi chiến trường lộn xộn của state.

Đừng cố đấm ăn xôi tự viết custom hook nữa, vì thế giới đã có React Query lo liệu việc này rồi.

Tại sao useEffect lại là "kẻ thù" của việc fetch data?

Khi dùng useEffect để gọi API, bạn đang bắt React làm những việc nó không hề giỏi. Nhiệm vụ chính của React là vẽ giao diện, không phải để quản lý bộ nhớ đệm (cache), đồng bộ hóa dữ liệu hay xử lý timeout mạng.

Nếu cứ ép nó làm, bạn sẽ gặp cảnh trang web nháy liên tục vì data chưa kịp load, hoặc người dùng chuyển tab rồi quay lại thì dữ liệu đã cũ rích. Để trang web thực sự mượt mà, đôi khi bạn cần kết hợp cách dùng Debounce & Throttle, nhưng với những luồng dữ liệu phức tạp thì chừng đó là chưa đủ.

Bạn cần một "quản gia" chuyên nghiệp hơn để lo liệu phần dữ liệu ngầm này.

React Query vào việc: Xóa sổ hàng chục dòng code thừa

Hãy tưởng tượng React Query (hay tên mới là TanStack Query) như một người trợ lý cực kỳ mẫn cán. Bạn chỉ cần bảo: "Ê, lấy cho tôi danh sách sản phẩm", nó sẽ tự động chạy đi lấy, tự lưu vào kho, tự biết khi nào data bị cũ để đi lấy lại.

Trong lúc chờ đợi, nó báo lại cho bạn biết biến isLoading đang là true để bạn quay vòng xoay loading.

// Thay vì viết useEffect dài dòng, code của bạn sẽ gọn như này:
const { data, isLoading, isError } = useQuery({
  queryKey: ['products'],
  queryFn: fetchProducts
});

Không còn useState, không còn mảng rỗng vô tri trong useEffect. Mọi thứ trong file React của bạn trở nên sạch sẽ lạ thường.

Phép màu của Caching và Background Fetching

Điểm ăn tiền nhất của React Query nằm ở cơ chế caching tuyệt đỉnh. Lần đầu tiên người dùng vào trang, nó sẽ fetch data và lưu lại vào bộ nhớ. Khi họ bấm sang trang khác rồi quay lại, nó sẽ lôi data từ cache ra show ngay lập tức—trải nghiệm nhanh như một cú click chuột.

Ngay dưới ngầm, nó vẫn âm thầm gọi API (background fetching) để lấy dữ liệu mới nhất đắp vào. Giao diện không hề bị khựng, và người dùng không phải nhìn thấy cảnh loading mệt mỏi.

Đó chính là trải nghiệm người dùng tinh tế mà mọi Frontend Developer chuyên nghiệp đều nên hướng tới.

Còn thao tác thêm, sửa, xóa thì sao?

Nếu useQuery dùng để lấy dữ liệu, thì useMutation sinh ra để xử lý các hành động làm thay đổi database (như POST, PUT, DELETE). Nó giúp bạn bắt được chính xác trạng thái khi nào đang submit, khi nào thành công để hiển thị thông báo toast.

Kết hợp công cụ này với cách React 19 Actions xử lý Form, bạn sẽ có một bộ combo hoàn hảo. Khi mutation thành công, bạn chỉ cần gọi một hàm duy nhất để yêu cầu dữ liệu cũ tự động refresh. Bạn có thể tham khảo thêm tài liệu chính thức của TanStack Query để thấy sức mạnh thực sự của nó.

Việc dẹp bỏ useEffect để chuyển sang một thư viện quản lý state server là bước trưởng thành bắt buộc của mọi dev React. Code viết ít hơn, ứng dụng chạy mượt hơn, lại ít bug hơn.

Nhưng khoan, giả sử data từ API trả về bị sai cấu trúc so với dự kiến thì bộ công cụ xịn cỡ nào cũng không cứu được giao diện của bạn khỏi cảnh trắng trang. Bạn đã biết cách dựng một lớp giáp bảo vệ dữ liệu trước khi đẩy nó lên UI chưa? Lần tới, chúng ta sẽ đào sâu vào cách "ép xác" dữ liệu nhé.

/Thảo luận

Bình luận

0