Suggest an editImprove this articleRefine the answer for “What does the cleanup function do in useEffect()?”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)The **cleanup function** is a function you return from `useEffect`, which React calls automatically before the component unmounts or before this effect runs again if its dependencies have changed. **Key point:** it helps avoid memory leaks, duplicate subscriptions, and unnecessary calls by releasing resources such as timers, events, and sockets.Shown above the full answer for quick recall.Answer (EN)ImageIt helps **avoid memory leaks, duplicate subscriptions, unnecessary calls, and errors** like > "Can't perform a React state update on an unmounted component". --- ## Definition > A cleanup function is **a function you return from** `useEffect`, > which React **calls automatically**: > > - before the component unmounts > - or before this effect runs again (if its dependencies changed) --- ## Syntax ```javascript useEffect(() => { // The effect body - runs on mount or update return () => { // Cleanup - runs on unmount or before a new effect run }; }, [dependencies]); ``` --- ## When exactly it's called | Scenario | When cleanup fires | |---|---| | The component **unmounts** | Once, before it's removed from the DOM | | An effect **dependency** changed | First the cleanup of the old effect, then a new run | | The component **re-rendered**, but dependencies **did not change** | Cleanup is not called | --- ## Example 1 - clearing a timer ```javascript useEffect(() => { const id = setInterval(() => { console.log('tick'); }, 1000); return () => { clearInterval(id); // cleanup on unmount console.log('cleaned up'); }; }, []); // [] → the effect fires once ``` What happens: - On mount, a timer is created. - On unmount (when the component is removed), cleanup stops the interval. --- ## Example 2 - unsubscribing from events ```javascript useEffect(() => { const handleResize = () => console.log(window.innerWidth); window.addEventListener('resize', handleResize); return () => { window.removeEventListener('resize', handleResize); // cleanup }; }, []); ``` If you skip cleanup, the handler **stays active** even after the component is removed, causing a memory leak. --- ## Example 3 - when dependencies change ```javascript useEffect(() => { console.log('Running effect for user:', userId); return () => { console.log('Cleaning up before the new effect for user:', userId); }; }, [userId]); ``` What happens: - When `userId` changes, React first calls **the cleanup of the old effect**, then runs **the new effect**. - This matters for cancelling old requests, closing connections, and so on. --- ## Example 4 - cancelling asynchronous requests ```javascript useEffect(() => { const controller = new AbortController(); fetch(`/api/user/${userId}`, { signal: controller.signal }) .then(res => res.json()) .then(console.log) .catch(console.error); return () => { controller.abort(); // cancel the request if the component unmounts }; }, [userId]); ``` If the user quickly switches `userId`, the old request is cancelled, and the new effect starts from a clean state. --- ## Why cleanup matters Without cleanup functions, you can end up with: - **Memory leaks** (timers, subscriptions, WebSocket, listeners) - **Duplicated effects** on updates - Errors like: > "Can't perform a state update on an unmounted component" --- ## Analogy in class components | Function components | Class components | |---|---| | `return () => {...}` inside `useEffect()` | `componentWillUnmount()` | | `useEffect(() => {...}, [deps])` | `componentDidUpdate()` + `componentWillUnmount()` combined | --- ## Mini behavior table | Action | Effect runs | Cleanup runs | |---|---|---| | Mount | Yes | No | | Update with changed dependencies | Yes | Yes (before it) | | Update without changed dependencies | No | No | | Unmount | No | Yes | --- ## Summary > The cleanup function in `useEffect()` is **a mechanism for cleaning up side effects**, > which React calls **before the component is removed or before the effect runs again**. It: - frees up resources (timers, events, sockets), - prevents leaks, - guarantees the component always operates in a "clean" state.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.