Check out a free preview of the full Complete Intro to React, v9 course
The "useEffect Hook" Lesson is part of the full, Complete Intro to React, v9 course featured in this preview video. Here's what you'd learn in this lesson:
Brian discusses the useEffect hook which provides a place for "side effects" in the application. A common use is fetch requests to an API. The useEffect hook will trigger the request once or anytime a dependency changes.
Transcript from the "useEffect Hook" Lesson
[00:00:00]
>> Brian Holt: So if you are having issues or just wanna see where I'm at here, we're at, four dash hooks where we learned about use state, by far the most common hook that you'll use. The next, we're gonna talk about the next most common hook that you're gonna use, which is use effect.
[00:00:21]
>> Brian Holt: So, state is all about statefulness in your component of things that can change over time in your component. This will be frequently tied to forms but you could easily write like a clock, right? Or something like that or something that, and the other thing is effects will be usually be used with state as well.
[00:00:39]
So they tend to combine and compose. But let's talk about effects, effects like stands for side effects, right? So you have some component and it has something that's gonna happen outside of it. Frequently this is gonna be like an API request, right? So you're gonna go reach out to some API, it's gonna come back with data and you will see that.
[00:01:06]
But this could be like, let's say you have something that you wanna show a clock in the date time or something like that. You could be doing that with an effect because you can think of time as a side effect to your component, right? It's anything that's gonna be inputting into your component that's not just user input or something like that, so,
>> Brian Holt: Let's go do that.
[00:01:31]
So make sure your API server is running because we actually are going to hit the API now. So let's go to order.jsx. This needs client, just make sure you have that if you don't. And we're gonna go to order.jsx and we're gonna import use effect from React and we have pizza, cool.
[00:02:03]
>> Brian Holt: We're gonna be doing some currency conversions here. So this is now just built into the browser, which is super nice.
>> Brian Holt: Number format, you give it what format you want, feel free to put this in your own locale. I'm gonna show you how to do it with dollars.
[00:02:30]
>> Brian Holt: So this is currency, and I want the currency to be USD. So, we're gonna load in pizza types. So right now we just have a flat list of all of these pizza types, but I want this to be a dynamically populated of all of our different pizzas.
[00:02:46]
I, being the generous course creator that I have, I've created 32 pizza types for you. And we're going to use all of them. Most of them look terrible, just to be aware of that. So const, another hook here, another useState hook, pizzaTypes,
>> Brian Holt: SetPizzaTypes,
>> Brian Holt: Equals useState with an empty array, right?
[00:03:23]
So this is basically gonna say like start with nothing and then we will progress from there. And then I'm gonna have a loading hook. This is gonna be useful for that, you can say like set loading to be true. And we can show the user a nice spinner and not render stuff that's not available yet.
[00:03:43]
And then once everything has loaded, you can say set loading to false, and then you can show them whatever they need to know. So, useState, we're gonna start by having the form be loading, right? Because it won't have all the pizzas loaded yet.
>> Brian Holt: Okay, cool, here we're gonna say let price and selected pizza,
>> Brian Holt: If it's not loading, I'm gonna say select pizza equals pizza types.find, pizza,
>> Brian Holt: Pizza type, triple equals pizza.id.
[00:04:43]
So why are we doing this? We're gonna be keeping track of just the ID of the pizza type that's been selected. We have to go actually find inside of our array of pizza types the correct one and we're gonna do that by its ID. And you notice these are not hooks despite the fact that they're immutable.
[00:05:02]
This is cuz it's kind of derivative state, right? So we can use this state up here to find this state, this doesn't actually need to be a hook because it's always going to be a function of these. Sorry, these are always a function of these, right? So the price is going to be whatever the pizza's price is, right?
[00:05:22]
The selected pizza is always going to be the pizza type that matches in pizza types, right? So, view has this concept of derivative state, I think Svelte has it as well. Doesn't exist in React, you just keep track of them in normal variables,
>> Brian Holt: Okay, so now we're going to adhere that selected pizza is going to be the correct pizza object that we've gotten back from our API.
[00:05:54]
>> Brian Holt: We're gonna write a function here called fetchPizzas, async function fetchPizzas, pizza types rather, pizza type. And this is just gonna be a really normal fetch command. So, we're gonna say const pizzaRes equals await fetch/api/pizzas, const pizzaJson equals await pizzaRes.Json. SetPizzaTypes to be PizzaJson
>> Brian Holt: And set loading to be false, cuz we'll be done loading at that point, right?
[00:07:02]
>> Brian Holt: All right, so we have this side effect function that we wanna call. Where do we call it?
>> Brian Holt: I can't just say fetch pizza types here. Why is this a bad idea? It would run each time the component is rendered. You got it, it would run every single time that the component rendered.
[00:07:22]
You're basically DDoSing yourself, right? So that's not a good idea. How can I run this at the beginning, right? That's all, I only wanna do it once, when the component first loads, right? Effects, you found the need for effects. This is exactly what effects are for. Use effect, you give it a function of like, hey, I need you to do this kind of outside of the render cycle.
[00:07:48]
So if you find that's exactly what effects are for, it's like I have my renders, and I have things that need to happen outside of the renders, and I wanna kind of control when that happens. So in this case, we're gonna say fetch pizza type. This isn't still quite what we want it to do, this is still going to schedule an effect after every single render.
[00:08:11]
So how do we tell it, hey, we only want this to change once? There's a second parameter here of like, hey, whenever this variable is different from the previous render, do it again. So, let's say here we put, I don't know, pizza size.
>> Brian Holt: Now, every time the user selected a different pizza size, this effect would get run again.
[00:08:40]
That's not actually what we want, right? We want it to run once, right? Just at the beginning. So how do we do that? Well, we just don't give it anything, right? We just give it an empty array, right? And that's saying, run this once, and then you're not tracking any variables here, so you're never gonna run it again.
[00:08:59]
Make sense, okay.
>> Brian Holt: You'll have to excuse the backwards walk into the logic there, but usually, people see this for the first time. It's like, why is there an empty array there, right? And they get really upset by that, so I'm trying to walk you back into, why that empty array exists there.
[00:09:21]
It does make sense, it's a little dense to look at, that's a lot of syntax in one line of just curly bracket, square bracket, square bracket, round bracket, or round parenthesis, right? It does make sense. Okay, next question people might ask me, why can't I just make this an async function?
[00:09:42]
I think Burton, you literally just asked me this. Async functions return what? Promises, they always return a promise. No matter what, if it's an async function, the return type is always a promise. And effects, the return type matters. I'm not gonna show you anything today where it does matter, but let's say you wanted it to run once and you wanted it to run at the end, not the beginning.
[00:10:07]
This can be useful for clearing timeouts, that's usually the time that I do it, or canceling, using an abort token to cancel a request, or something like that. You can return a function, get rid of this async.
>> Brian Holt: This is how you would do that. The return here is the cleanup function.
[00:10:29]
>> Brian Holt: So, all of this to say, you don't need to do that right now. It's a fairly rare thing that you need to clean up, but that's how you would do it.
>> Brian Holt: And that's why we can't just make this async, right? That's why I make an async function up here and then call it for my effect.
[00:10:45]
I now have selected pizza price, we're now fetching all of the pizzas, so eventually this is going to be full of pizza types here. Now, this is like one of my favorite things again about React. By doing everything this way, I basically could just treat all of my code down here as if pizza types already existed.
[00:11:11]
It reads very optimistically in the sense of I just assume that the data is gonna be fed here eventually. And it makes the code not full of if this, then that, right? It's usually just like read as if the code is here, right? Let's go replace the options here.
[00:11:33]
>> Brian Holt: PizzaTypes.map, pizza, and here we're just gonna do an option key equals pizza.id, we'll talk about keys here in just a second. And value equals pizza.id. And then we want pizza.name to be down here, pizza.name. All right, so this is a little dense here. Let's talk about this for just a second.
[00:12:00]
It's all concepts you know though. Between the curly braces can be any JavaScript expression, whatsoever, right? If you're familiar with map, it's a JavaScript function that you're taking an array of something and you're turning that into an array of something else, right? It's just a transformation from an array of 1, 2, 3, 4, and you say, map double, that you'd get 2, 4, 6, 8, right?
[00:12:26]
It would just transform one to the other. We have an array of pizza types, and we wanna transform that into an array of components, right? Or elements as it were, not that that really matters. That's all we're doing here, is we're just turning an array of objects into an array of React stuff, right?
[00:12:50]
And if you remember, under the hood, like we saw, what is JSX transforming that into? It's an array, right? So if we give it an array of components, it knows exactly what to do with them. So that's why map here works, we're turning an array of these pizza objects just into an array of options.
[00:13:09]
Makes sense? We follow, right? Obviously there's some errors here, but I think if we refresh this, we should see,
>> Brian Holt: Lots of pizza types.
>> Brian Holt: Which is kinda cool, right? So if we refresh, look here at the network, you can see here we have a, I'm looking just at XHR, which are Ajax requests here.
[00:13:41]
You can see it's hitting the API, it's getting a response back here of all of the different objects, right? And it's turning that into an array of options.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops