DEV Community

Cover image for How does useEffect really work?
charliekroon
charliekroon

Posted on

How does useEffect really work?

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]);
Enter fullscreen mode Exit fullscreen mode

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:

  1. 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!")
    }, []); 
    
  2. 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!")
    });
    
  3. 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]);
Enter fullscreen mode Exit fullscreen mode

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)