</>
⌕
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 = true chỉ 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.
🃏 Ôn bằng flashcard