React and TypeScript Typing Class-Based Components
This course has been updated! We now recommend you take the React and TypeScript, v2 course.
Transcript from the "Typing Class-Based Components" Lesson
>> So we have class-based components, cuz, if you're writing a brand new app, you might use functional components everywhere and hooks everywhere, so on and so forth. But if your code base is a few years old, maybe it's predominantly class-based components. If it's a few years old, maybe it's a mixture between class-based and functional components.
[00:00:24] What do you do, this whole time we've just ignored the fact that class-based components exist. Let's stop ignoring that for a second and figure out what it might look like. So, here, we've got a fairly simple, kinda counter application. And right now, again, it doesn't do anything. What we wanna do is some of the stuff we saw, if you stay, we added some state management to it, and some events.
[00:00:53] And we'll see some of the edge cases in a class-based component. And then we'll also see how those edge cases might also apply in functional components as well, and how to deal with them. So the syntax is a little bit different, because the syntax for class-based components is a little bit different.
[00:01:11] One of the things is, we have counter extends component, at which point here, we would have two type arguments. Those angle brackets, they deal with something called generics, and we'll talk about a little bit. You almost think of them as variables for your type system. And really, the two things that it takes is the shape of MyProps, like we saw in the props argument in our functional components, and then also the shape of our state as well.
[00:02:01] The state is probably gonna be the count that seems relatively easy. The count is going to be what kind of incident. So we'll say the CounterProps is the incident, is a string. And we'll say, type CounterState, Is a number. All right, so far so good. All right, so now we'll swap those in.
[00:02:33] CounterProps. CounterState. A red squiggly happens down here where it's, yeah, you told me that we're gonna take an incident here but you didn't pass me an incident, so I need to fix that. Cool and we'll just pass it in, Is this.props. And we'll go ahead and use it, Right here.
[00:03:13] All right, so the props pretty straightforward, nothing in particularly interesting about that, but let's also look at the state. So here, we'll define the state, and we'll say the type of that is CounterState. And that count is 0. All right, and so now we've got that in place, and now we can grab the count as well.
[00:03:46] This.state, and we'll toss it in with that 0 is now, Sweet. So we have that in place. We do need to get some of the buttons working, right? And stuff along those lines. One of things you might see is, why did I define it twice? Generally speaking, I can get away without it.
[00:04:12] If I kinda look here, you can see the count is number, there were previous versions where you might see in a lot of places cuz it helped with some of the type hinting in older applications. So I included it here as well, so you might see it. But these days, if I removed it still worked.
[00:04:30] I personally include it cuz I still think the computer doesn't care, right? I do think as when you read large class-based components, it can be somewhat helpful as well. So I'd say it's a personal life decision that I have made. All right, so let's figure out how to increment and decrement.
[00:04:52] These will be pretty straightforward, there's nothing particularly interesting to see here. I will say this.setState. And that will take whatever the count is. And we will go ahead and we'll return an object where the count is count +1. All right, decrement, you can take a lucky guess. Is gonna subtract 1, and reset will set it to 0.
[00:05:30] Those are the easy ones. In fact here we can actually say that, Count is 0. Nothing particularly special there. What will be interesting is this form element, right? Because here we actually, the first time so far, that we are directly interacting with an element or an event, right?
[00:05:56] So far, we've gotten through our time together without really having to deal with that. And that sweet period of innocence is now over, and we're gonna have to figure out. Now, I left a hint in some of the early slides, so it shouldn't be super surprising how this goes down.
[00:06:13] But let's take a look at it. And then we'll go ahead and we'll say, event, we need to know what the event is. I'm gonna just be blissfully ignorant of that for a second. And we'll say, this.setState, and we'll say count is event.target.value, right? And that will work, except when you say countCount, we're called changeCount cuz that makes sense.
[00:06:47] TypeScript is angry with us. TypeScript event is any, this is cuz we know deep in our soul that we're gonna put this on the form when they hit the Submit button. Typescript doesn't know that, TypeScript doesn't have a soul. And so we need to say, hey, you made a function on a class property.
[00:07:14] I don't know anything about what's happening here. So we need to tell it what event is going to be. And as I kinda hinted that earlier, we might say something along the lines of, We do a ChangeEvent, or something along those lines. I've got a Submit button there, let's go with this one first, and we'll kinda take a look at it, momentarily, which is HTMLInputElement.
[00:07:44] Here as well, and okay, now it's angry about count. Look at that. One of my favorite things about the web. It's my single favorite thing, is that despite the fact that this input field has the type of number and only accepts numbers, in the DOM, the event will still be a string on the input field, regardless of that.
[00:08:10] So we have to coerce into a number, you can use percent, I'm just gonna use a plus sign. But TypeScript has figured out, hey, I know that the value on InputElements, when they change, is always gonna be a string, even if it's the typed number. So it actually caught that for us and it's all fair.
[00:08:47] Let's just go ahead and quickly wire this stuff up. This.increment. This.decrement, nope, reset was in the middle. Despite how I defined the methods. And this.decrement, and then here we'll just do it on change for now. We can talk about how to figure it out for something else. I use the one that we used in the example on the slide earlier just now.
[00:09:25] But let's also say this.changeCount, cool. And we'll also set the value, To count, as well. All right, so, it's got a 0 increments, everyone's favorite, silly React component. You can also do it in here and it changes as well. So Steve, what do we do here? We just have to memorize all of the different APIs for all the different events, and just commit it all to memory and do it like that?
[00:10:00] My argument is no, my argument is a lot of the times your tools can help you. And your tools can guide you into what the right choice is. So let's say, hypothetically, we wanted to do the kinda form submission to change the number instead. And we'd have to actually keep some state of what the form is, and we're not gonna do that all the way right now, cuz that's more of an exercise in React than learning too much about TypeScript.
[00:10:27] But we can hover over this on Submit, and you can kinda see some of the answers here, which is you kinda have it right here. You can look at, so what would be the right typing for a form submission event, right? Well, instead of this, up top we had React.ChangeEvent or just ChangeEvent that I pulled off the React library.
[00:10:49] On HTMLInputElement if we wanted to make it on form submission, we could actually see that it's React.FormEvent on an HTMLFormElement, right? So a lot of times you do not necessarily need to go digging in the docs or anything along those lines. You can actually just use some of the tooling available to figure out, okay, this on submit, this is what it would expect.
[00:11:12] So here is how I need to define that in my actual class method.