Complete Intro to React, v7 Fetching Data in componentDidMount
This course has been updated! We now recommend you take the Complete Intro to React, v8 course.
Transcript from the "Fetching Data in componentDidMount" Lesson
>> We can't use user effect here, right? So, how are we gonna get information back from the API? Cuz we have to do something when the component first load, cuz we have to request the animal data from the API. So, how are we gonna do that? Well, these class components have something called lifecycle methods.
[00:00:18] So, there's one that we can create here called component. You can see this even completes here, which is kind of cool. ComponentDidMount is the one that we're interested in. So, componentDidMount, this function gets run after it gets rendered to the DOM for the very first time, right? So, it's gonna run this once.
[00:00:41] And when it runs at once it's gonna do this, it's gonna say loading then after that rendering is complete then it's gonna called component did mount. So, if you remember, it's gonna be basically the same as us effectbBlur this, right. Where you have like this empty array of like no dependencies, remember when we did that earlier in the course, component did mount is essentially the same thing as this.
[00:01:07] There's probably some pedantic differences that we could get into that I don't care about. But suffice to say that the end up being the same thing. Does that make sense? So, now we have this function that we can run whenever this first gets mounted and we can do our API request here.
[00:01:25] And the nice thing is we can make it async. So, that like all the code looks really nice. We can use async await. I don't believe it has to be async if you don't need it to be, but I just kind of always make it async cuz it makes it easy for me.
[00:01:40] So, we're gonna make a request to the API. So, const res equals await, fetch. And then we'll do http colon // pets- v 2 .dev-API's.com/pets:ID= And we're gonna get this.props.params.id So, that's another big difference here that we should probably discuss. We're used to taking props in here, right?
[00:02:30] As a parameter to the render function. That's not the case in class components here. So, what you're gonna do instead is you're gonna refer to it as this stopprops.whatever, right? Which is what we're doing here. We're gonna expect something called props.params.id. Okay, and then after res, we're gonna say constant JSON equals await res dot JSON.
[00:03:07] And then here, instead of calling our set function, so, const JSON equals await res dot JSON and then what you used to do is, he used to call use state, so, you'd have like you set pets function or set breed function. There's just like one function now called set state.
[00:03:27] So, what you do now is you say this dot set state, and then you're gonna basically call it with like an update of what you whenever you wanna set your state to be. So, in this particular case, We could call set state twice here and say like loading false, right?
[00:03:48] Cuz this loads in a loading true state, right? And this would update it. So that loading would be set to false. And then we could call again with this .setState. Have whatever JSON comes back with. And what do I have to call it with, I can't remember JSON dot pets zero, like that.
[00:04:19] Cuz this is gonna be like the animal breed city state description name of the animal that we found, right. However, we can make this, so, a little bit better and just do it all at one time and say this dot set state with an object dot assign. And we can do loading: false.
[00:04:49] And here we'll put jason.pets0. So, what I have here on line 17 is equivalent to what we put here on line 19. It's just done in one statement so that react gets it all at once instead of getting it in two different sets, days. Typically react to smart enough to say.
[00:05:09] I'm gonna wait. I'm gonna batch all these changes and do them at once, but you can never have any guarantee what reaction is going to batch of what it's not. And it's bad if it doesn't match this because then it's gonna re-render twice, right? Cuz you called set state twice and it'll cause a rear-end her every time that you call setState.
[00:05:28] So, it's better where you can to just call setState once. It's not always possible and that's okay. Typically, we're splitting hairs here, right? But, this is easy enough for us to just do it in one fell swoop, so we're gonna do it it that way. So, that's how state works with component, components is gonna keep track of this internal links.
[00:05:48] Let's do it this way. This like internal state object of like loading false and then as soon as we were gonna set this eventually to true and then it's going to add things like name, Luna and City Seattle, right? And then if you call set state again with I don't know, maybe she moves to Salt Lake City, right?
[00:06:12] And so, that's how class components are they have this internal state that's mutable that you can change, but the only way that you can change it is by calling set state. The reason why you wanna call set state as opposed to just saying this dot state dot name equals something else, right, is that React is not tracking this, right?
[00:06:34] You have to let React know that state is changing so that it can queue updates appropriately. This is not Angular with two way data binding. Terrible idea we should have never done it, right? So, does that make sense of like how state is working with class components? Yeah, Mark.
>> Reason for using fetch over x use.
>> Yeah, why are we using fetch here instead of using like a library like axial or something else? Cuz fetch is built into the browser, axial is a powerful, requests library. And it's also fairly nice to use. But we're literally just doing GET requests to an API.
[00:07:26] And if you're doing that fetch is more than enough. I mean, this is a pretty pleasant API to use. It's kind of strange. You have to do like the await twice, but, You just get used to it, I suppose. I don't know, I got used to it. I don't have a reason other than the simple thing works for me.
[00:07:44] One last thing here is, we need the ID to get in here, right? Cuz this is a route, it's gonna come from React router. And we need to use use param because that is the only way to get param out of React router. So, how do we do it?
[00:08:00] Well, you're probably gonna not be super impressed with this way of doing it, but that's how you have to do it. So, we're gonna wrap it in another component. Wrapped details equals this and then here we can say const params equals use params. And then we can just return details with the params passed in.
[00:08:29] Okay, and then here you just export rat details. I imagine many of you are looking at like what the actual hell are we doing here, right. But, the other way of doing it was relatively the same way like the way that we used to do this with React router or with basically like Redux or anything like that they were called higher order components.
[00:08:52] It's essentially the same thing just with more ceremonial circumstances it felt more official. This is actually probably a way simpler way of doing it rather than exposing two different API's just using a hook and then passing that into the component. Ends up being the simplest answer and this is actually fairly obvious of how this works whereas higher order components.
[00:09:10] There was a lot of indirection of how stuff was working and made, fairly confusing. So, any questions about that, yeah, Mark.
>> Is there any difference between using object assign versus the spread operator.
>> So, here, Yeah, you could have used object spread. You absolutely could have said, In fact, let's just rewrite it that way.
[00:09:45] That's actually a fairly good way of doing it. I think that the reason I did it the other way is just force a habit to be honest with you. Less dense if we do it this way, I forget about object spread. So, this and what I had before are functionally the same thing.
[00:10:10] This is called the spread operator that it's basically doing object.assign. In fact, if you look at the polyfill for it, it literally does objects that assign. Yep. Okay, so let me just go make sure that this actually works with it. I anticipate that it should. And it does.
[00:10:34] So now, we actually get like a nice little lunar page. So, it looks like everything is working here. Yeah, I showed you how to use hooks with class components and it's just make a wrapping component. That's a fairly common thing to have to do in React now. Especially the inner out interoperate between the two.
[00:10:57] I showed her how to refer to props, right, instead of that being passed in here to render it just gets assigned to be on this. So, the one thing I'll say with class components in particular is you have to make sure that you know what this is. With componentDidMount we know every time the componentDidMount gets called, this is going to be correct.
[00:11:17] But let's say we use setTimeout in here. Let's say for whatever reason we needed to wait five seconds before we did this. You could do a setTimeout and then you do Blur, do stuff and then after five seconds do it. And then here if I tried to say like console dot log, this dot state.
[00:11:47] What is this stick gonna be here? Tenant the job interview, I'm just kidding. It's gonna it's gonna be undefined, right? Because it's not called in the context. We're getting into like splitting details. Now, there's lots of good front of masters stuff on this, but this is actually gonna be, we called outside of the context of react, right?
[00:12:10] So, this is not actually going to refer to, the details instance. I mean, I think we can just load it up and you'll see. I should have put a shorter one because it's actually gonna wait five seconds. It did? Because you're using the arrow.
>> You had like an actual function.
>> Yeah, you're right. So, I mean, you can see even I get tripped up on the stumps and I've been doing this for forever. Let's make this one. So, now you can see it's undefined. Indepent depends on what style of function I wrote, right? So, an arrow function doesn't create lexical context is actually, so, it does create a see, I can't even remember off the top of my head.
[00:12:56] I'd have to go think about it some more, but suffice to say that the arrow function will allow you to use the function context wherever it was invoked. Whereas if you call function, it's actually going to use it from this call side, and the call side has no context and with set timeout, for example.
[00:13:13] In other words, this becomes very important and you need to know what this is. Most of the time it's what you expect it to be. But if you're doing things like set timeout, and then the other big got you is with event listeners, because event listener is doing it from the same place, which is context less.
[00:13:33] Cool, okay, that's my spiel. With React Router five, they used to have something called with router which is, basically what this did it passed a instance of router in as a prop. So, instead of doing this you do like export default detail or with router Details like that.
[00:14:04] And that's how you do this kind of thing. They got rid of that API because they're like this is basically the same thing and allows you to have more control over it. So, in the end, I think it ended up being a better API. I linked the issue in there where they explain their reasoning if you wanna get into the depth of why they did it this way.
[00:14:26] And then the other thing here I wanted to talk about I showed you component did mount, there's like component will unmount, there's component did unmount, there's can component did catch, which is for errors. We'll actually look at that one here in a little bit. There's a bunch of life cycle methods here that I'm not gonna show you because like I said, class components are way less important than they used to be.
[00:14:47] So, there are several things that you could only do in class component that catches one of them like doing error boundaries. And there's sometimes I still like writing class component because, I would write this one as a function component because there's nothing here that we're doing this really requires a class component and they're just faster to write.
[00:15:08] And also now that's the way that the ecosystem works. But sometimes when I wanna use like all of the lifecycle methods and those kind of like line up with my line of thinking, I'll use a class component but that's kind of the exception now as opposed to the rule.
[00:15:27] Yeah, I think that's a good feels, most time use function components. If you have something that like fits your frame of thinking in the class components right away then use a class component. Yeah.
>> Would you say this also false into that category of like, right, it is a functional component first and if you use effectors and give you the granular control that you want and maybe switch to a class component
>> Yeah, I'd be okay with someone saying that. Yeah, I mean, they're pretty easy to switch back and forth