The unused power of useEffect
In this post, we will discuss the useEffect hook offered to us by React Hooks which lets us perform side effects in function components.The release of React Hooks offered a new method of using React where we do not need class-based components. Before the introduction of React Hooks, all state was managed in class-based components. Function components were just used as dummy components i.e. just used to display data passed in by the use of props. Function components also offered no lifecycle methods, so knowing when the component had mounted or when it updated was very difficult and could only be handled in class-based components In addition to this, we also need some lifecycle method that would behave similarly to componentDidMount and componentDidUpdate , along came useEffect which gave us the power to handle side effects in function components. In React, there are two common side effects, side effects that require clean up and side effects that don't, useEffect can handle both of these side effects. By the end of this post, you will be able to: With the above knowledge in place, you will be able to build out an entire application with just function components. To get the most of this article, we assume you're familiar with the component basics in React & React Hooks and also core JavaScript. If you do not know any of the above but would like to learn, here are some great resources: Now let's get into it! We will first look at how we can implement useEffect into your application. The React team has made this quite simple for us. The interface for useEffect is quite simple, it accepts two arguments, a function, and an array: The first thing we need to do is import useEffect: Then we can use it in our component: Now let's look at the main points of useEffect : With all the theory we need in place, we will now look at an example in order to put our knowledge to use. It is very common to do an animation when a user sees your page, to do this we normally use a reference to the HTML element. In react, we use the useRef hook to achieve this: Then on your element: We then have reference to that element from the .current property of our sqaure ref. In our example, we want a square to be rotating when our page loads. We will be using the Greensock library for our animation as it keeps the animation code simple so we can focus on useEffect . So our component could look like this: The problem with this is that the .current property isn't available to us when the page loads. We will see the following error in the console: To remedy this issue, we can put the animation code inside of the useEffect function which won't fire until the component has loaded. Now our div will rotate when the component has loaded, if you have used React before then this is very similar to componentDidMount . The console will also have no errors. Here is a link to a Codesandbox that you can play around it: Updating the document is also another very common example of using useEffect . So if you had an array of names declared like so: We can store one of these names in state : We can add a button that onClick will pick a random name: So when this button is clicked we want to update a div that has the class of title . The code will look as follows: We want this to change every time that currentName is updated, we do this by adding the above like inside of useEffect . So every time our currentName changes, useEffect tells our component of what it needs to do when an update is performed i.e. in our case update the innerHTML . The is the pattern of useEffect , state updates --> run function . In our next example, we will look at changing this pattern. Here is the complete Codesandbox: Our final example is the most complicated but will help to even further our knowledge of useEffect . In this example, we will also be using the second argument that we can pass to useEffect . For our API, we are going to use the free PokeAPI . We can query this API with an id and it will return the Pokemon who belongs to that id , the id can be passed as a prop to the component. Finally, to fetch the data, we will be using axios . Our request will look like as follows: So above the ${id} part of our query string is the id that the user of the component will provide as a prop . When fetching data with React Hooks, you should place the code in useEffect so that the data will be fetched when the component mounts. You can do this like so: We declare some state initially where we can store our data, and then using the setter ( setData ) we can update state of our component. You will also see that I am using async and await which is handling the promise being resolved. If you were to run this code you would encounter a nasty bug, since we haven't supplied an array of dependencies (i.e. the second argument) we will get stuck in an infinite loop. Our component will mount, then update our state which will cause the useEffect function to fire again which will go through the entire process again and again and again...... How do we fix this? We supply an empty array to the second argument of useEffect . This second argument is to define all the variables that the hook depends on i.e. the variables it needs to watch for changes, in our case, it depends on none so this will stop useEffect running on component update. Great! So there is one last thing we have to deal with. The above code in Codesandbox gives the below error. It is telling us that the callback we pass to useEffect shouldn't be asynchronous and instead, we should place the asynchronous function inside of the callback. Thankfully, this is quite an easy fix. We need to create a function inside useEffect that will be our async function and then within that function we can make our request with await and set our state. Then we simply call that function within the useEffect block. Here is how it looks now: Great! That is how you fetch data with useEffect , not so bad right? Here is a Codesandbox that you can play around with: Today we learned: In addition to the above, we also learned how to use useEffect to manage that action we take when our component updates. We saw how useEffect can handle side effects in our components such as DOM manipulation and API requests. If you're interested in learning further, I really recommend checking out this long-form post by Dan Abramov . Have a great day.