A Complete Beginner’s Guide To UseEffect Cleanup |By HRブログ

Source | Figma

With useEffect, you perform side effects from within functional components, which is an important concept for mastering React today.

Here are a couple of examples of side effects that will get you thinking about effects:

- fetching data
- directly updating the DOM
- timers.

What is the useEffect cleanup function?

A use-effect cleanup function can prevent memory leaks and remove unwanted behavior from the function before our component unmounts.

Here are some use-cases for this:

- Clean up subscriptions
- Clean up modals
- Remove event listeners
- Clear timeouts

Now take a look at the code below. Did you notice anything off?


import React from "react";
export default function App() {
const [count, setCount] = React.useState(0);

React.useEffect(() => {
setTimeout(() => {
console.log("effect is running!");
setCount((count) => count + 1);
}, 1000);
});

return (
<div className="App">
<h1>You clicked {count} times!</h1>
</div>
);
}
Note — How it keeps counting even though it should only count once!

Remember that side effects belong to useEffect which is running on every render. That means that when the count changes, a render happens, which then triggers another effect.

How can we fix this?

There are several ways to control when side effects run. You should always include the second parameter which accepts a dependency array.

Without it, effects run after every render and setting the state will trigger the effects again. An infinite loop may also happen if you specify a value that always changes in the dependency array. You can tell which one by removing them one by one. However, removing a dependency you use (or blindly specifying []) is usually the wrong fix. Instead, fix the problem at its source.

So, to fix the issue, we will write our useEffect cleanup function which is pretty easy and straightforward to do. We return a function from our useEffect as seen below:


useEffect(() => {
//effect is running
return () => {
//clean up the effect
}
}, [input])

When do cleanups run?

If your effect returns a function, React will run it when it is time to clean up. Don’t worry if it’s hard to grasp this, we’ll better understand it with the examples below.

Let’s fix our counter demo from before and introduce a cleanup function that will run when the Counter component unmounts and will stop the timer:

In this example, the useEffect hook is dependent on a variable that runs once and then runs again whenever the count variable updates.

import React from "react";
export default function App() {
const [count, setCount] = React.useState(0);
const [total, setTotal] = React.useState(0);
React.useEffect(() => {
setTimeout(() => {
console.log("effect is running!");
setTotal((count) => count * 2);
}, 1000);
}, [count]);

return (
<div className="App">
<h1>You clicked {count} times!</h1>
<button onClick={() => setCount((count) => count + 1)}>+</button>
<p>Total: {total}</p>
</div>
);
}

💡 Note — If there are multiple dependencies, they should be included in the useEffect dependency array.

//clean up the timer at the end of the useEffect hookimport React from "react";
export default function App() {
const [count, setCount] = React.useState(0);
React.useEffect(() => {
let timer = setTimeout(() => {
console.log("effect is running onMount!");
setCount((count) => count * 2);
}, 1000);

return () => {
console.log("component unmounts");
clearInterval(timer);
};
}, []);

return (
<div className="App">
<h1>You clicked {count} times!</h1>
<button onClick={() => setCount((count) => count + 1)}>+</button>
</div>
);
}

With useEffect, things are synchronized by default. If you want to run an effect and clean it up only once (on the mount and unmount), you can pass an empty array ([]) as a second argument. This tells React that your effect doesn’t depend on any values from props or state, so it never needs to be re-run.

If you pass an empty array ([]), the props and state inside the effect will always have their initial values. While passing [] as the second argument is closer to the familiar componentDidMount and componentWillUnmount mental model, there are usually better solutions to avoid re-running effects too often. Also, don’t forget that React defers running useEffect until after the browser has painted, so doing extra work is less of a problem.

Conclusion

Thank you for reading, and let’s connect!

Feel free to subscribe to my email newsletter and connect on Twitter.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
HRブログ

Talks about #realworld, #finance , #economics, #crypto and #technology.