Giới thiệu vấn đề cache invalidation
Tanstack Query quản lý dữ liệu async, nhưng khi cập nhật sản phẩm, danh sách vẫn giữ dữ liệu cũ nếu không invalidation đúng. Điều này gây lỗi hiển thị và giảm trải nghiệm người dùng.
Kỹ thuật invalidate query theo key
Sử dụng queryClient.invalidateQueries với key cụ thể sau khi thực hiện mutation. Khi key bao gồm tham số, cần truyền đúng cấu trúc để chỉ invalidate những query liên quan.
Ví dụ mutation cập nhật sản phẩm
import { useMutation, useQueryClient } from '@tanstack/react-query';
import axios from 'axios';
const useUpdateProduct = () => {
const queryClient = useQueryClient();
return useMutation(
(data) => axios.put(`/api/products/${data.id}`, data),
{
onSuccess: (_, variables) => {
// Invalidate list và detail của sản phẩm vừa sửa
queryClient.invalidateQueries({ queryKey: ['products'] });
queryClient.invalidateQueries({ queryKey: ['product', variables.id] });
},
}
);
};Cache sharing với pagination
Khi danh sách có pagination, key thường dạng ['products', { page, limit }]. Để invalidation toàn bộ trang, dùng queryClient.invalidateQueries({ queryKey: ['products'] }) mà không truyền params.
Thêm optimistic update để giảm độ trễ UI
Optimistic update cập nhật cache ngay trước khi server trả về, giảm thời gian chờ. Cần rollback khi request thất bại.
Code optimistic update
onMutate: async (newProduct) => {
await queryClient.cancelQueries({ queryKey: ['products'] });
const previous = queryClient.getQueryData(['products']);
queryClient.setQueryData(['products'], (old) => {
if (!old) return old;
return {
...old,
pages: old.pages.map((page) => {
return {
...page,
data: page.data.map((p) => (p.id === newProduct.id ? { ...p, ...newProduct } : p)),
};
}),
};
});
return { previous };
},
onError: (err, newProduct, context) => {
queryClient.setQueryData(['products'], context.previous);
},
onSettled: () => {
queryClient.invalidateQueries({ queryKey: ['products'] });
},Quản lý cache thời gian sống (stale time)
Đặt staleTime phù hợp để tránh refetch không cần thiết. Ví dụ, danh sách sản phẩm có thay đổi ít, đặt staleTime: 5 * 60 * 1000 (5 phút).
Query config
useQuery(['products', { page, limit }], fetchProducts, {
staleTime: 300000, // 5 phút
cacheTime: 600000, // 10 phút giữ trong bộ nhớ
});Kết luận
Áp dụng invalidate theo key, optimistic update và cấu hình staleTime giúp dashboard ecommerce phản hồi nhanh, dữ liệu luôn đồng bộ. Tham khảo khóa học "[Full Course] Ecommerce Dashboard Fullstack Clone" tại đây.




.png)



