cleanup function in useEffect hook in react
In React, the useEffect
hook allows you to perform side effects in function components. The function you return from the useEffect
hook is called a cleanup function. This cleanup function is used to clean up any side effects that were set up in the useEffect
call. It's particularly useful for managing subscriptions, timers, or any other resources that need to be cleaned up to avoid memory leaks and other unintended side effects.
Why Return a Cleanup Function in useEffect
- Memory Management: Cleaning up resources like event listeners, timers, or subscriptions prevents memory leaks.
- Avoiding Unintended Side Effects: Ensures that any side effects from previous renders do not interfere with the current render.
- Consistency: Keeps your component's behavior consistent, especially when dealing with asynchronous operations or external resources.
Example: Basic useEffect
with Cleanup
Let's look at an example where we use useEffect
to set up an interval and clean it up when the component unmounts or when the effect is re-run.
import React, { useState, useEffect } from 'react';
function TimerComponent() {
const [count, setCount] = useState(0);
useEffect(() => {
const intervalId = setInterval(() => {
setCount(prevCount => prevCount + 1);
}, 1000);
// Cleanup function to clear the interval
return () => {
clearInterval(intervalId);
};
}, []); // Empty dependency array means this effect runs once when the component mounts
return (
<div>
<p>Count: {count}</p>
</div>
);
}
export default TimerComponent;
Explanation
-
Setting Up the Effect:
setInterval
is used to increment the count every second.- The
intervalId
is stored so it can be cleared later.
-
Cleanup Function:
- The function returned by
useEffect
is the cleanup function. clearInterval(intervalId)
ensures the interval is cleared when the component unmounts or before the next effect runs.
- The function returned by
Example: Cleaning Up Event Listeners
Another common use case is adding and removing event listeners.
import React, { useState, useEffect } from 'react';
function ResizeComponent() {
const [windowWidth, setWindowWidth] = useState(window.innerWidth);
useEffect(() => {
const handleResize = () => {
setWindowWidth(window.innerWidth);
};
window.addEventListener('resize', handleResize);
// Cleanup function to remove the event listener
return () => {
window.removeEventListener('resize', handleResize);
};
}, []); // Empty dependency array means this effect runs once when the component mounts
return (
<div>
<p>Window width: {windowWidth}</p>
</div>
);
}
export default ResizeComponent;
Explanation
-
Setting Up the Effect:
handleResize
updates the state with the current window width.window.addEventListener('resize', handleResize)
adds the event listener.
-
Cleanup Function:
window.removeEventListener('resize', handleResize)
removes the event listener to prevent memory leaks and unexpected behavior when the component unmounts or before the effect re-runs.
When the Cleanup Function Runs
The cleanup function runs in the following scenarios:
- Before the component unmounts: Ensures that any side effects are cleaned up to prevent memory leaks.
- Before running the effect again: If the dependencies of the effect change, React will clean up the previous effect before running the new effect.