React and TypeScript, v3

Typing useState Exercise

Steve Kinney
Temporal
React and TypeScript, v3

Lesson Description

The "Typing useState Exercise" Lesson is part of the full, React and TypeScript, v3 course featured in this preview video. Here's what you'd learn in this lesson:

Steve instructs students to build a simple form in React using useState to manage input values and handle form submission. He demonstrates how TypeScript provides immediate feedback on type issues, explains the difference between string and number inputs, and shows how event types and context help prevent common errors while enabling reusable, type-safe handlers.

Preview

Transcript from the "Typing useState Exercise" Lesson

[00:00:00]
>> Steve Kinney: Your job. We've got this fun form here, right? For setting the value to something, right? Can you both one, use a useState to then get us a draft value for that input field, and then to get the onSubmit to actually set the actual count, so on and so forth, right? Again, just getting your hands dirty as we kind of build on top each step to greater and greater glory. Let's get this form working. So our goal was just again, like, add a little bit more state and then we're going to turn the knob of complexity up just a little bit.

[00:00:43]
We'll turn it back down, but we'll turn it up. All right, so for having that kind of like input, say, I don't really know what to call it, we'll call it draft count. Draft count, set draft count. Maybe I learned how to spell, who knows? UseState, we'll start that off with a 0 as well. And so in this case, we'll go ahead and we will pop that over in here. And we'll say that onChange, we will simply take that event and do set draft count is then event.target.value.

[00:01:44]
And we got some, oh, I got a name of the same variable name though, that's usually important. We've got some fun things that we'll deal with in a moment, probably now-ish, but like, let's get the rest of it in place by just doing the piece here where they actually hit the submit button and we do the thing. And you're going to notice that we've got some red squigglies. I'm not like ignore, I am ignoring them, but not for too much longer in this case, where now we'll just say, we'll prevent default, and then we're going to say that set count is going to be the draft count.

[00:02:27]
Right, and again, if I did not have TypeScript, then theoretically, I wouldn't see a red squiggly here, and like, I would probably, because of the way JavaScript worked, not even know that I've got a little type issue, because if you add a number to a string, works most of the time, but let's just make sure our actual app works, so we will say update counter, and then we'll increment, and oh, there was a subtle bug that if I was using JavaScript, that I would have had, in this case where the value is technically a string, despite the fact that it's a number input, right?

[00:03:06]
And so we have a few options. There is a valueAsNumber, and that will then, the red squigglies go away. And like the nice part is if I go back to the previous one, like, before I even had to like, oh, let me go run my tests and all of those things and wait for the test suite to run, I can basically already know that I have a problem. What the problem is, is pretty clearly stated to me, which is argument type string is not assignable to the parameter type of set action number, right?

[00:03:34]
Because it's a string, and so I can see that the immediate feedback, again, like I suspect that I don't necessarily have to sell you on the value prop here of TypeScript, but it's nice, it's nice when we get it. So now we can say valueAsNumber and hit reset. We'll give that entire thing a reset real quick, and we'll set this to 34, and then we'll increment it, everything's good. Okay, so there's some other fun tasting notes, like, for instance, event.target isn't like universally available across all of the events, right?

[00:04:11]
But we didn't get a problem of like, hey, did you check to see if there's a target and that it has a valueAsNumber like TypeScript's like, I know that it does. Do you know how it knows that it does? Because it's in this change handler here on an input, so it knows if we hover over it. That any function, there's no TypeScript in that onChange function, right? But because of the types in React, React knows that the only functions that this takes is a change event handler for an HTML input element, right?

[00:05:00]
And so even if we hover over target, we wrote no TypeScript. But it knows that event.target is an EventTarget and HTML input element. Right? Because it knows that any function, if this only takes change handler events of HTML input elements, and you gave it this function, it is going to then infer that everything in this is correctly typed. The interesting part and the kind of the like central to the thesis here is like, the moment that it is not 100% sure, then you need to help give it some hints.

[00:05:34]
So for instance, if we grab really honestly any of these, we'll grab this one because it's a fun one, and we'll move it up here, as you see a lot of times, we'll do like const handleSubmit, and we'll just say it's this function. And you're like, it is no longer nearly as happy about any of this, right? Go put that in there. Like here it's like, yeah, that seems legit as long as it's the one that takes an object, yeah, cool, cool, cool.

[00:06:10]
It's like e or the event in this case, implicitly has the any type, because as far as TypeScript knows, like, you know that you need to handle submit, you know that you're passing in there. TypeScript like this is a function assigned to a variable. I don't have the context that I had back when it was literally on the event handler, right? And so that's where you kind of off-road a little bit and go on your own.

[00:06:41]
Luckily, hmm, I wonder how I figure out how to find the type that it ought to be. I could Google it or ask ChatGPT or hopefully Claude Code has the answer, or I could just like hover over the onChange thing and see that like, we can, we have a React change event handler in this case, and that will theoretically do the trick, right? So for instance, we said, oh, look, the red squiggly line vanished, right, because we literally copy and pasted by hovering, right, over what it is, and now it is legitimately a React change handle event on an input element.

[00:07:23]
So if just to like watch the world burn, if I put it onto the reset button where, like, you can see that it's like, yo, you can't put input event change handlers on a click handler for a button because the event is going to be an event target is going to be an HTML input element and not a button, yada yada yada yada yada, right? And like, otherwise if we just literally probably took, it wouldn't have a valueAsNumber on this one because it knows that target should be a button down here and so it is protecting us from all sorts of little tiny things in this case, right?

[00:08:03]
But like when it doesn't have the context of exactly where it ought to be, then in that case, like, we end up in a situation where we have to give it at least a hint. And like, in most cases, you can just like import just a click event handler, right? And what's kind of cool about this is like, theoretically, you could now pass this function to, like a, any like input event. This is now a reusable, fun little function that we can pass around, even something that is a change input event, input element will work with checkboxes and a few other things, right?

[00:08:46]
If you just said this was HTML element, right, it still works down here. You don't get yelled at because like, it turns out that HTML input element is an element, right? But it's like, it's even cool with knowing that this is like event.target does truly exist, right, because you defined it here. But it's like only input elements, not a lot of other things like have that valueAsNumber. There might be other fun HTML elements that have that one could theoretically go and find that out.

[00:09:19]
I don't care to. So it will kind of protect you because right now all it knows is some kind of, it doesn't know if it's a span or a button or an input element, it doesn't know anything. So the more hints you give it, right, the more place, like, the better it can protect you from yourself, right? And so, again, as if it has the context, you don't have to give it any information. If it doesn't have the context, you have to figure it out.

[00:09:42]
What's up, Julian? What would be the reason to use valueAsNumber over something like the number function like number construction? You can do that too. Okay. Right, valueAsNumber exists, so I don't have to do anything, right? But the question was like, why don't I just coerce it into a number? So if it was value in this case, right, we get yelled at because that's a string, you could do a number like that, and now it's a number, everything's good.

[00:10:20]
You can be real fancy and use a plus sign to coerce it into a number as well. Fun historical fact is that like, I for the longest time thought you had to do that, and then one day I was standing here and Mark told me that valueAsNumber exists and it changed my life forever. I did not know that until I was literally standing here and Mark corrected me at one point. So, you know. But yeah, so you can.

[00:00:00]
I did for years. ValueAsNumber also exists too, so whichever one makes you, but the nice part is like, you know, with confidence that it doesn't matter because TypeScript didn't yell at you. Right, but yeah.

Learn Straight from the Experts Who Shape the Modern Web

  • 250+
    In-depth Courses
  • Industry Leading Experts
  • 24
    Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now