Control component side effects with React useEffect

Ryan Harris
InstructorRyan Harris

Share this video with your friends

Send Tweet
Published 2 years ago
Updated 2 years ago

The useEffect hook is used to handle side-effects caused by a component's actions such as fetching data from an API, attaching event listeners to the document or manipulating the DOM itself.

useEffect takes two values: a function defining the logic to be executed and an optional array called the "dependency array". By default, effect hooks will run every time the component re-renders, however, you can control its execution by defining and changing the values within your dependency array.

useEffect(() => {
	// Runs every time the component renders
})

useEffect(() => {
	// Runs only on initial render
}, []) // Optional second argument: dependency array

useEffect(() => {
	// Runs only when 'apiData' changes
}, [apiData])

Ryan Harris: [0:00] If we want to set the title of our document, we can add a useEffect hook here and import it from "react", come into our App component, and say useEffect. We'll say document.title = ${new Date().toLocaleString()}. Now, you can see that the title of our document has been updated.

[0:30] In this example, we didn't add any event listeners, so we don't have to return anything from the hook. However, if we were to add an event listener in this new useEffect hook, we would need to return a function that cleans it up.

[0:43] If we added window.addEventListener and listened for the resize event and fire the undefined handleResize function, we would need to return an anonymous function that called window.removeEventListener, so that when this component unmounts, the listener is removed from the window.

[1:02] In both of our examples, the hook would fire every time the component renders. However, if we only want that to happen on the initial render, we would need to pass in a second optional argument called the dependency array.

[1:15] Let's take a look at this a bit more closely. We'll come down here into our return and add a button. We'll make it say Re-render. Then above, below all of our other state hooks, let's add a new variable called number, and a function called setNumber. Equals useState, and initial value will be .

[1:36] To have this button cause our component to re-render, let's add an onClick prop. This onClick will take a function that sets our number to (number + 1). Since this hook has no dependency array, it will run every time this component renders. If I come over into the browser and click this button, you'll see that the timestamp in the tab at the top will change every time.

[2:08] If we come back into our code and add an empty dependency array, you'll see this changes the behavior. Now, when I re-render the page, the timestamp is set, but when I click the Re-render button, nothing changes. This is because an empty dependency array means the effect will only run on the initial component render.

[2:29] Let's add another useEffect hook. I'll take a function as usual and here's the dependency array, an empty array that means it only executes on initial render. We'll call fetchDataFromAPI and then we'll take the response and set it to state here locally in our component.

[2:52] Let's save our file and come back over into the web browser. We'll open our developer tools and go to the Network tab. If we refresh the page, we should see one network call going to the API. There it is.

[3:07] Hooks with an empty dependency array run only once. If they have values in the array, they'll run only when those values have changed. Let's add another hook, useEffect. We'll say if the day or data value stored is state above change.

[3:25] Let's run this code, if (data), const dataForDay = parseDataForDay. Then we'll say setDayData(data) and the key will be dataForDay. Now, if we use these toggles to change the value of day, you'll see that the hook is rerunning and parsing new data, which is displayed below.

[3:57] In summary, the useEffect hook is very flexible and can be used in a variety of cases. Its execution happens every time the component renders unless you pass it a dependency array, which controls its execution to either the first time it renders or when certain values change.

Maven
Maven
~ 6 months ago

The NASA API returns a 200 but the incorrect data. It returns empty dayData. On app, I see this error:

TypeError: Cannot read properties of undefined (reading 'mn')