Check out a free preview of the full Complete Intro to React, v8 course
The "Effects" Lesson is part of the full, Complete Intro to React, v8 course featured in this preview video. Here's what you'd learn in this lesson:
Brian demonstrates how to implement a search request for an initial set of pets on page load using the useEffect hook. The completed hook will also only make a fetch request on form submit to avoid making excessive API calls.
Transcript from the "Effects" Lesson
[00:00:00]
>> So, we're gonna start making some network request now. So, I had this app and I need to make a request to an API, to get a new list of breeds, right? Because every time I switch from bird, which is gonna have parrot and cockatiel and cockatoo and things like that.
[00:00:22]
And I go to cat, which is gonna have tabbies and main coons and things like that. I need to request a new set of breeds, right, from the API. So we're gonna use something called an effect, use effect. Okay, okay, we'll do breed list in a second. We're actually gonna do the search part first.
[00:00:47]
So that you can actually search for pets from the API. So, we are gonna use still in effect for this. And effect is basically something that's going to happen outside of your component, right? So I have my location, animal and breed. But then once I have those and user clicks Submit, I want that to go out to my API and get a new list of pets so that the user can see what they've searched for, right?
[00:01:15]
That's what these effects are for. It's like go retrieve this from some other place or go do something outside of the life cycle of my component. So typically that's API requests. I'm gonna say most of the time that's an API request, but it could be like, go get this from local storage, or go retrieve this from some other location, or go save this to an API.
[00:01:35]
Go post this to an API, or go save this to local storage. But it's something outside of your normal kind of life cycle there. Okay, so we're gonna add another user here which is gonna be pets and set pets. Equals use state, that's going to be just an empty array of pets that we've retrieved from the API.
[00:02:03]
And then here I'm gonna say use effect and this is gonna be a function. Okay, and then at the beginning of whenever this gets set, I'm gonna say requestpets. And I'm gonna write this function, I'm gonna go to the API and request pets from the API. Okay, and then here, I'm gonna make an async function called request pets And const res equals await fetch backticks.
[00:02:45]
Notice, I'm using backticks here not single quotes or double quotes, but backticks says the one next to the one on the keyboard. HTTP or HTTPS, either ones fine I think. pets-v2.devdash apis.com8/pets question mark animal = animal and location =${location}, &breed= This is a template string if you're not familiar with JavaScript, and this is basically how you insert like a animal from here into it, right?
[00:03:47]
That's what template strings are for. Okay, this is gonna go out and fetch this from the API. If we want the JSON back from it so we're gonna say const JSON equals await res.JSON. And then we're just gonna call set pets, this function up here that we just created with json.pets.
[00:04:15]
Okay, so now we're gonna have a whole list of pets coming back from the API. We would like to render that as well. So underneath our form here. Yeah, underneath the form but still inside of the larger div, going to say pets.map. It's going to take in a pet and it's going to return a pet from./pet.
[00:04:50]
And we're going to pass in name={pet.name} animal={pet.animal} and breed={pet.breed}. Now one more thing here before we close this off. We were rendering out all these various different components. What happens if, I filter my list differently, so now I'm sorting by breed now instead of sorting by animal, So I have the same group of elements in my array, but I've decided to order them differently.
[00:05:38]
According to React, all it knows is that array changed and it doesn't know how it changed. So what it's gonna do is it's going to destroy everything inside of that render tree and totally render it from scratch. Which is unnecessary, right? It'd be better if it's just like, you just re rendered the same things, but in a different order.
[00:06:00]
I'm gonna, instead of destroy everything and re-render it. It'd be cool if I could just swap them, right? So you can give it this thing called key, and if you give it some sort of unique handle per thing, it can figure that out on it's own. So each one of these pets has an ID.
[00:06:18]
So if I give it this key pet = ID like this, it can now have a handle on the like, okay? I'm just gonna swap these instead of destroying everything. And the other thing is React will yell at you until you give it a key. The key here is that the key here.
[00:06:38]
Nice, good job, Brian. The key here is that it's a unique identifier per object in your array. So even if you swapped all of the various different things, the ID would be the same. So name would be a bad key here, right? Because if I have three different bingos, right?
[00:06:56]
It's gonna think that this bingo is the same as this bingo and then it's gonna get mad. So make sure that it's unique per thing. There has to be some sort of unique identifier. If you don't have a unique identifier, you don't have to give it one. A bad idea here is you can give it an index.
[00:07:16]
But if I swap bingo from 0 to 3, the index doesn't follow it, right? So, it's gonna destroy and re-render it anyway, or worse it's gonna get like not gonna work well, so, don't do this either. Okay, so you did pet here, I imported pet at the top as well, make sure you do that.
[00:07:41]
And then one more thing here. And a fact Runs, every single time, you re-render the application. So, you re-render this component by default. So, this is going to request the pets every single time that I type, which is not what I want, I only want that on submit events, right?
[00:08:09]
So how do we do that? You can give it an array of dependencies. And here if I give it nothing, then it's only going to request once at the beginning and then it's never going to do it again, which is actually what I want. The only time after this that I want to call request pets is on Submit ,right?
[00:08:31]
On the form submit, which so that puts the user in control of when this research is for things. So let's go take a look at this make sure it's working. You can see here I'm getting things back from the API now, which is cool, right? But now even if I click Submit and things like that it's not going to work.
[00:08:57]
What happens if I wanted to automatically research every time they changed animal? While they put an animal in here, this is now telling React, hey, every time that animal changes, I want you to rerun request pets. So now if I do this, Now it's doing it every single time that I change this, right, which is kinda cool.
[00:09:22]
But notice that it doesn't change every time I type in location. How would I do that? Well, give it location as well. And now, every time that I type in here, It's researching. Every time that I type something in there. Honestly also not what I want. I don't want it to do it ever after the first time, so again, empty array.
[00:09:59]
That's what I wanted to do in the first time. It's gonna give you a warning and say, hey, you have this request, pet's thing. And it's not a dependency on this. Typically what the exhaustive hooks rule wants you to do is it wants you to declare all of your dependencies like every time this changes, please do that.
[00:10:20]
It's actually not what I want right now, but it's looking for you to do this. And then it's gonna say like well, this is not a good idea. Maybe you should move this inside of here and so he was like okay I'll do this inside of it and then it wants you to do a location, animal, And breed.
[00:10:40]
And then finally, this is going to be satisfied. But this is not the behavior that I'm actually looking for, right? The behavior that I'm actually looking for is on submit for this research. So what I had the first time was actually what I wanted. So I'm going to delete that.
[00:11:01]
We're gonna say on submit here. And this is a function. The first thing to say is e.prevent default cuz we don't actually want it to fully form submit, right? And then we're going to say request pets. This is now the behaviour that we're looking for. So if I go over here and refresh, and I click cat, nothing has searched now but if I click Submit, now I get cats.
[00:11:35]
That's the workflow I was looking for. Okay, I still have this like annoying, like warning, right? So you can actually click on this. You can say disable, React hooks exhaustive for this line. And by doing that, now it actually going to ignore that and go. The way I actually have my notes is this way.
[00:12:14]
So how do we wanna do that? I'm gonna do it this way. Set, not disable next line, just disable line. And there we go. You'll find that you'll do this somewhat frequently with exhaustive depth. That's why it's a warning and not an error. Even though it's a warning and like my, CI would pass with this.
[00:12:43]
I like to be explicit as like, I'm explicitly, I know that there's an error here and I am ignoring it. Because it's not the behavior that I wanted to describe with my code. That makes sense? Do the dependencies make sense here? You're basically just telling me like, hey, when do I run this effect again?
[00:13:02]
And by giving it an empty array, the answer to that question is never run this again. Run it once so that the workflow here, it's gonna do its first render without using this effect. And then immediately after that effect has finished or the render has finished, so that you can like show a loading screen or whatever you need to do there.
[00:13:22]
As soon as that's done, then run this effect. By giving it an empty array, you're saying never do this again. After that very first time, never do it again. If I leave this off, Now, it's gonna run all the time. No matter what, if it detects anything ever changing ever, look at that.
[00:13:46]
Like it gets really janky. So don't do that either. Cuz it's rendering every time that it calls pets, right? So don't do that either. Yeah.
>> Before hooks, would we have done this with component did mount is this effectively replacing component did mount?
>> Yes, that's exactly what's replacing.
[00:14:04]
I think it actually runs literally at the same time. So yeah, I think it's totally the same. We'll look at class components here in just a second, so we'll get more into the depth on that.
>> Is this a good example of best practices for using a third party API in a form?.
[00:14:23]
>> Yeah, this is exactly how you do it. [COUGH] We're about to get into React query, which is kind of like the next level on top of that. But for pure React with nothing else, this is how you do it. Really the only way to do it
>> Why is it necessary to run request pets initially?
[00:14:46]
>> So it's good question, why do I wanna run it initially? Notice that this has a list of dogs, a list of list of pets on load. If I don't run this effect, now there's nothing, right? Nothing loads on initially. So you wanna do it so that something loads initially, right?
[00:15:10]
All right, so now I have learned on all that. So you're showing these or something.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops