Senior #useeffect#data-fetching#abortcontroller
Race condition khi fetch trong useEffect và cách xử lý bằng AbortController?
⚡ Trả lời nhanh
Khi dependency đổi nhanh, response cũ có thể về sau response mới và ghi đè state sai. Cách xử lý: cleanup của effect gọi `controller.abort()` (hoặc cờ `ignore`), bỏ qua `AbortError`. Tốt hơn nữa là dùng thư viện (TanStack Query/SWR) hoặc Suspense.
useEffect(() => {
const controller = new AbortController();
setLoading(true);
fetch(`/api/user/${id}`, { signal: controller.signal })
.then((r) => r.json())
.then(setUser)
.catch((e) => { if (e.name !== "AbortError") setError(e); })
.finally(() => { if (!controller.signal.aborted) setLoading(false); });
return () => controller.abort(); // id đổi hoặc unmount
}, [id]);
abort()hủy request thật (tiết kiệm băng thông); cờlet ignore = truechỉ bỏ qua kết quả.- Cleanup chạy trước effect kế tiếp nên mỗi lần chỉ response của lần mới nhất được dùng.
- Với search-as-you-type nên debounce và/hoặc
useDeferredValue. - StrictMode (dev) mount, unmount, mount lại effect: request đầu bị abort, đó là hành vi đúng, không phải bug.