Transcript from the "Class Components" Lesson
>> Brian Holt: All we've talked about so far are hooks, right? How to do state with hooks? It used to be called stateless functional components and now people just call them function components. But if you see that terminology, those mean the same thing, right? It just means that a function that's not a class.
[00:00:18] I'm going to show you how to do the other way of doing components which are class components. And they function in one most ways very similarly and in other ways, a bit differently.
>> Brian Holt: So we're gonna make the details page be a class component.
>> Brian Holt: So what I'm gonna do here is I'm gonna say class Details extends React.Component,
>> Brian Holt: Okay?
>> Brian Holt: But other than that, it works relatively the same way. The one hard requirement of every class component is it must have a render method.
>> Brian Holt: It will not work unless you have a render method.
>> Brian Holt: And then this render method works mostly like how a function component works, right?
>> Brian Holt: So one thing to keep in mind as well is that,
>> Brian Holt: You can't use hooks with classes, right? So use state will just simply not function inside of a class component.
>> Brian Holt: Okay,
>> Brian Holt: So, we're gonna put in a render method here in just a second.
>> Brian Holt: But let's go ahead and put in a componentDidMount.
>> Brian Holt: So, component, you can see here that it's actually gonna try and complete it for me cuz it knows it's coming from React.Component, that's how it knows all of these methods.
>> Brian Holt: These are called lifecycle methods.
>> Brian Holt: And, right today, we're gonna talk about componentDidMount. And componentDidMount is a very, very similar to use effect in the sense that it runs when it first start up, but then it stops. It doesn't run anymore after that, okay? Whereas use effect, you have to give it the dependencies and things like that.
[00:02:28] ComponentDidMount just as like I'm gonna do this once when I first get created and then I'm done doing this thing, okay? So that's what we're gonna do with componentDidMount.
>> Brian Holt: ComponentDidMount is useful for things like doing Ajax request, which is exactly what we're gonna do, right, when someone loads the page.
[00:02:47] We wanna go to the API and get the pet information back from the API, right?.
>> Brian Holt: So, that's exactly what we're gonna do when we say pet, which we are going to import that from import pet from frontendmasters/pet.
>> Brian Holt: I wanna say pet.animal, it's a single animal.
>> Brian Holt: And then we're going to pass it.
[00:03:19] We want to pass that the ID that we're getting from here, I like it from /details/1, right? We wanna pass it this number 1 right there, right, that ID that we're getting from the URL. So the way we're gonna do that is with this.props.id. So rather than getting that in as an argument like we were with functions it comes up this.props.
[00:03:44] You can be assured that anything that's passing from the parents is gonna come in from this.props. The one thing to keep in mind with this.props is its immutable, you can't change it. So, a child receives props from its parents, and it can't change them, it can only read them, right?
[00:04:01] They're read-only in that sense.
>> Brian Holt: Does that make sense, yeah.
>> Brian Holt: Okay, and then after that, this is a promise. I'm gonna say .then and we're gonna get the animal back from the API.
>> Brian Holt: It's a pair function here.
>> Brian Holt: And we're gonna say this.setState.
>> Brian Holt: And we're going to get the name is going to be animal.name.
>> Brian Holt: You could put like a return here, it'll just stop giving you all the red lines. We'll fix that in a second and I'm just getting sick of the red lines. [LAUGH]
>> Brian Holt: Name,
>> Brian Holt: Animal.name will do, animal is,
>> Brian Holt: Animal.type.
>> Brian Holt: Here will do location which will be a template string because we have to put a couple things together here.
>> Brian Holt: We're gonna do animal.contact.address.city.
>> Brian Holt: Space, animal.contact.address.state.
>> Brian Holt: Description will be animal.description.
>> Brian Holt: And the media will be animal.photos.
>> Brian Holt: And breed will be animal.breeds.primary.
>> Brian Holt: And then the other thing that we're gonna do here is we're gonna say, loading false.
>> Brian Holt: So we're gonna say, loading false.
[00:06:17] So, when we first load the page, we're gonna put it in a loading state, right cuz you're grabbing something from the API, right? And then whenever this comes back from the API, we're going to set that to loading false. Now the way that we're gonna set it to be a loading state is we're gonna say constructor up here.
>> Brian Holt: Let's say, constructor, and constructor will take in the props. And you have to say super props. This is just something kinda, it's an odd ritual that you just have to do. It's going to be constructed with properties, and you have to handle those properties up to react, right?
[00:06:51] So that's what this does. The super props says, hey call the constructor on my parent class which is a React.Component. Is that make sense? If you don't do this, react will yell at you. So, just get used to doing it.
>> Brian Holt: Okay, here, I'm gonna set an initial stage, some would say this.state =,
>> Brian Holt: Loading, oops,
>> Brian Holt: True.
>> Brian Holt: So let's talk about this.state versus to this.props. This.props is information that you get from your parent class that's handed down to you, right? This is, again, what was coming in via parameters before. Now again, we don't have hooks. So we don't have any way to keep stateful things using hooks, right?
[00:07:40] So the way that we do that with class components as using this.state. Whereas this.props immutable and only comes from the parent. This.state is self-contained within the class. So no other components can modify its state, its master of its own state, right?
>> Brian Holt: So in this particular case, I'm instantiating it like I'm creating the first set of state but everything after that I'll do with this.setState, right?
[00:08:08] So after I call this .setState here, this will update this state up here, right? So this will get a bunch of new state from all this stuff, right? And then this loading true, will be set to loading false.
>> Brian Holt: Make sense? Okay, so the thing to know about when I call this .setState, this is what's called a shallow merge, right?
[00:08:31] So, I mean, it might even literally just says Object, you can ignore this but just showing what it does. Object assign,
>> Brian Holt: oldState,
>> Brian Holt: newState, right?
>> Brian Holt: So that basically what that means is if any of these collide, like this one does with this one, it will over write this one, right?
[00:08:55] But everything else will just be additive. So if this had some other thing,
>> Brian Holt: This would not be overwritten, this would still exist afterwards, right? But it is shallow, right? So if I have deeply nested objects, those won't get overwritten, right, so it just does the top level.
>> Brian Holt: And that's how you do state with class components. This is how I've been doing state for a really long time until hooks came along.
>> Brian Holt: Something else I wanna call out here, notice these an arrow function here instead of saying function here.
>> Brian Holt: You’ve probably noticed that I use a lot of arrow functions just by the nature of how I code, this in this place, it's actually required.
>> Brian Holt: I don't wanna say required, it's very difficult if you don't do it this way.
>> Brian Holt: So why? Why is this a problem here? Well, if I put a function here, what is this?
>> Brian Holt: The answer is not what you would want it to be. [LAUGH] I don't actually know it's gonna be, but it's not gonna be what you'd want it to be, right?
[00:10:05] When I put function here, it creates a new context when this is invoked. This.then is going to be invoked somewhere else. That might be Window, it might be the promise itself. I'm not actually sure what it gets invoked on. But, if I do an arrow function instead this will get.
[00:10:23] It will not create a new context, which is what arrow functions do, they don't create new contexts, right? So this will be correct.
>> Brian Holt: Does that make sense?
>> Brian Holt: Some of classic components, what this is very important, right? It's actually one of the reasons why they chose to go the directions of hooks is because this is kind of hard to teach, right?
>> Brian Holt: It can be.
>> Brian Holt: There's just like a handful of things that you need to be aware of. And I think after that it's pretty to move past what this is.
>> Brian Holt: And, you can also put here in the then, you can put console.error. So if there's any errors in the API, so it will just log it out to the console.
>> Brian Holt: You should have better error handling than this, right? You should report it to your service and show that your error are some useful error message. This is not a course on error handling. They have a course on that, you should watch that. [LAUGH]