In the month of April I’ll publish a small blog series called “Questions from the past”. I’ll be going through my old notebooks from my first year as a developer and answer the questions I think are most important. Today we will discuss the workings of the useEffect
hook.
useEffect
is a React Hook that can be both useful and messy at the same time. I know there are already a bunch of blog posts on this, but I want to make it super clear for you when, how and why you can use it. Let's go into it!
You can use useEffect
to perform various tasks, such as fetching data, updating the DOM, optimising performance or cleaning up resources when the component is unmounted*.
Let’s take a look at the useEffect
hook, and analyse bit by bit what it does. To begin, here's the basic code for the useEffect
hook:
useEffect(() => {
// code to run on every render
return () => {
// clean up!
}
}, [dependencyArray]);
The dependency array
The dependency array is the second parameter of useEffect
. It’s called literally ‘dependency array’ because this is the array that useEffect
is dependent on. With that I mean that depending on what's inside the dependency array, your useEffect
will either run or not run.
There are three things that you can do with the dependency array:
- Leave it empty.
useEffect
will run only once when the component loads for the first time. This is because there are no dependencies that could trigger a re-run of the code.useEffect(() => { console.log("The component was loaded for the first time!") }, []);
-
Don’t include it at all.
useEffect
is called on every single state change.useEffect(() => { console.log("I ran because there was a state change!") });
-
Put a variable inside the dependencyArray.
useEffect
will run every time that variable changes.const [dogCount, setDogCount] = useState(0); useEffect(() => { console.log(`There are now ${dogCount} dogs!`) }, [dogCount]);
The return function
The return function (aka the Clean Up function) is called when the component is about the be removed from the screen, or when the useEffect
needs to cancel the previous effect.
For example, in this code snippet, the useEffect
will fetch user data every time the value of userId
changes.
const [user, setUser] = useState(null);
useEffect(() => {
let isRendered = true;
fetchUserData(userId).then(user => {
if(isRendered) setUser(user);
});
return () => {
isRendered = false;
};
}, [userId]);
When the component is first mounted, it uses the fetchUserData
function to get the data from the initial userId
. If the userId
changes while the component is still showing, the useEffect
hook makes sure that component only displays the data for the current userId
and not the old data.
When the fetchUserData
function returns with the user data, it uses setUser
to update the component with the new data. This makes sure that the component always shows the correct user data.
So, to sum it up: if you're using React, it's important to know how useEffect
works, the dependency array, and the return function. I know it can be confusing at first, but once you get the hang of it, it can really help make your React app better and faster.
*Component mounting is when React creates and adds a new component to the page for the first time. It sets up the component's initial state, properties, and children, and assigns it a unique identifier. After it's mounted, it can be updated with new information.
Top comments (0)