How to Cleanup in useEffect in React: Simple Guide
In React, you cleanup in
useEffect by returning a function from the effect callback. This returned function runs before the component unmounts or before the effect runs again, letting you clear timers, subscriptions, or other resources.Syntax
The useEffect hook accepts a function that can optionally return a cleanup function. This cleanup function runs when the component unmounts or before the effect runs again if dependencies change.
useEffect(() => { ...; return () => { ...cleanup... }; }, [dependencies])- The cleanup function is where you undo or clear side effects like timers or event listeners.
- The dependency array controls when the effect and cleanup run.
javascript
useEffect(() => {
// setup code here
return () => {
// cleanup code here
};
}, [dependencies]);Example
This example shows a timer that counts seconds. The cleanup stops the timer when the component unmounts to avoid memory leaks.
javascript
import React, { useState, useEffect } from 'react'; function Timer() { const [seconds, setSeconds] = useState(0); useEffect(() => { const intervalId = setInterval(() => { setSeconds(s => s + 1); }, 1000); return () => { clearInterval(intervalId); // cleanup stops the timer }; }, []); // empty array means run once on mount return <div>Seconds passed: {seconds}</div>; } export default Timer;
Output
Seconds passed: 0 (then increments every second)
Common Pitfalls
Common mistakes include forgetting to cleanup, which causes memory leaks or duplicate timers. Another error is not returning a cleanup function or returning it incorrectly.
Also, if dependencies are missing or incorrect, cleanup may not run when expected.
javascript
import React, { useEffect } from 'react'; // Wrong: no cleanup returned function Wrong() { useEffect(() => { const id = setInterval(() => console.log('tick'), 1000); // no cleanup function returned }, []); return null; } // Right: cleanup returned function Right() { useEffect(() => { const id = setInterval(() => console.log('tick'), 1000); return () => clearInterval(id); }, []); return null; }
Quick Reference
| When to Cleanup | How to Cleanup | Why Cleanup Matters |
|---|---|---|
| Before component unmounts | Return a function inside useEffect | Prevents memory leaks and bugs |
| Before effect runs again (if dependencies change) | Clear timers, cancel subscriptions | Avoids duplicate side effects |
| When using event listeners or external resources | Remove listeners or free resources | Keeps app performance smooth |
Key Takeaways
Always return a cleanup function from useEffect to clear side effects.
Cleanup runs before unmount and before the effect reruns if dependencies change.
Forgetting cleanup can cause memory leaks and unexpected behavior.
Use the dependency array correctly to control when cleanup happens.
Cleanup is essential for timers, subscriptions, and event listeners.