๐ฆ๐๐ผ๐ฝ ๐ ๐ฒ๐บ๐ผ๐ฟ๐ ๐๐ฒ๐ฎ๐ธ๐ ๐๐ป ๐ฅ๐ฒ๐ฎ๐ฐ๐
You see this warning in your console: "Warning: Can't perform a React state update on an unmounted component."
This happens when an async task runs inside useEffect. If your component unmounts before the task finishes, React tries to update state on a component that is gone. This creates a memory leak.
The Problem
When you fetch data, a race condition occurs. The data arrives, but the component no longer exists.
Example of the error: useEffect(() => { fetch('/api/data') .then(res => res.json()) .then(data => { setData(data); }); }, []);
The Fix
Use a cleanup function. You have two main ways to solve this.
- Use a boolean flag Set a variable to track if the component is still active.
useEffect(() => { let isMounted = true;
fetch('/api/data') .then(res => res.json()) .then(data => { if (isMounted) { setData(data); } });
return () => { isMounted = false; }; }, []);
- Use AbortController This is better because it stops the network request entirely.
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(); }; }, []);
Best Practices
- Always return a cleanup function for async tasks, subscriptions, or timers.
- Use AbortController for fetch calls to save bandwidth.
- Use a boolean flag if you cannot cancel the task.
- Check your dependency array to avoid stale data.
Why this matters
Proper cleanup does more than hide warnings. It prevents unnecessary re-renders. It stops bugs in production. It saves network resources.
Always plan for what happens when a component disappears.