๐ฆ๐๐ผ๐ฝ ๐ฅ๐ฒ๐ฎ๐ฐ๐ ๐ ๐ฒ๐บ๐ผ๐ฟ๐ ๐๐ฒ๐ฎ๐ธ๐
You see this warning in your console: "Warning: Can't perform a React state update on an unmounted component."
This happens because of async operations inside useEffect.
When you start a fetch call, a race condition occurs. If your component unmounts before the call finishes, React tries to update state on a component that no longer exists. This causes memory leaks.
The Problem:
useEffect(() => { fetch('/api/data') .then(res => res.json()) .then(data => { setData(data); }); }, []);
The component might be gone by the time the data arrives.
The Fix:
You must return a cleanup function. This function runs when the component unmounts.
Method 1: Use a boolean flag.
useEffect(() => { let isMounted = true;
fetch('/api/data') .then(res => res.json()) .then(data => { if (isMounted) { setData(data); } });
return () => { isMounted = false; }; }, []);
Method 2: Use AbortController.
This is the better way. It stops the network request itself.
useEffect(() => { const controller = new AbortController();
fetch('/api/data', { signal: controller.signal }) .then(res => res.json()) .then(data => setData(data)) .catch(err => { if (err.name === 'AbortError') return; console.error(err); });
return () => { controller.abort(); }; }, []);
Why cleanup matters:
โข It prevents unnecessary re-renders. โข It stops state updates on unmounted components. โข It cancels network requests to save bandwidth.
Always use a cleanup function for async operations, subscriptions, or timers. Use AbortController for fetch calls.