React and TypeScript React and TypeScript

Set State Without a Default Value

Check out a free preview of the full React and TypeScript course:
The "Set State Without a Default Value" Lesson is part of the full, React and TypeScript course featured in this preview video. Here's what you'd learn in this lesson:

Steve discusses how to explicitly specify the type in useState without the TypeScript type checker throwing an error.

Get Unlimited Access Now

Transcript from the "Set State Without a Default Value" Lesson

[00:00:00]
>> So the other question is, is there any case where you might to explicitly specify the type in use state? That is a great segue that I am going to use to kind of talk about one of our next problems we're gonna have to solve for. Which is, let's assume we're getting some from an API, right, like TypeScript inferred that hidden or is hidden and toggle hidden should be bullying because we pass it a bullying.

[00:00:25] But if we're fetching something from an API, it could at the very beginning, be something like perhaps, undefined or null or something along those lines. Right, at which point we don't know yet, which means TypeScript can't really infer anything yet. Which point we might need to be able to explain what's going on.

[00:00:47] So here in our application we wanna explain, we will just show like little character cards here. And there's some data in here as well. This is, right now we're gonna load it from another file simply because, I wanna make sure that If we use an API doesn't go down in six months or whatever.

[00:01:07] But we're going to basically use this promise called fetch character, which is going to immediately resolve, effectively simulate an API for us. And you can see a little bit about the character type and all the things it's gonna have in there as well, that we have defined already.

[00:01:22] But we're gonna load this, with a promise. So we can't just immediately hard code in that data, we have to be able to figure out, okay, we're gonna start out with null or undefined in this case, and then we'll go ahead and we will load the data and be able to begin to figure it out from there.

[00:01:41] Okay, so, let's look at this component and figure out what we might seek to do here. We wanna show the character information component, right? It's just simple. It's like a heading and a table that just shows all of those different attributes. You can kind of take a look at it over here.

[00:01:59] There's a little more room, which is it's effectively the character name, and then all the other properties and a table. There's nothing particularly special about it. We haven't done anything around that yet. And we don't necessarily have the characters yet. So we'll solve for that, which is we do know that eventually we do wanna have a given character that we load.

[00:02:22] So we'll say const character and set character Equals react I use state, but what is it going to be? Normally what we would have done in regular react so we just said null and we would have filled in later. We would have done a little null check at some point to make sure that it does what we think it's supposed to do.

[00:02:46] We might say something like character. And if we have it then show me that character information card. And you can see we get some autocomplete, the character Cool, that's character or null. Or you could also do and then do that instead. Right. Sweet, one of the problems that typescript is yelling at me right now about is saying, listen, hey, the character information component is expecting a character type to get passed in and you gave me null.

[00:03:30] And that's a legitimate concern. We need to deal with that in a second. But so TypeScript again, is looking at us if we don't have this file open, right?. It's trying to show us in the context of what we're doing. What the potential issue is now, we knew that that was going to be an issue.

[00:03:46] We're not particularly surprised by it, what we'll do is we'll use react at use effect, and we'll say, When this loads for the first time, go ahead and fetch a character. Then with the character Set the character. Cool. And you can see that it loads the character and puts everything in there as well.

[00:04:25] But you can still see it's angry with us, right? For a few reasons, it's like, hey, you can't pass in null. Now it's working but we told TypeScript originally that character was null cuz that was the first value of past and like what helped us in the last exercise is now slightly problematic for us in this one, right?

[00:04:44] You passed in null, I expected their character was always gonna get set to null, and then you set it to a character and even it's like well character is supposed to be null like it works this time. This is not cool. So really what we got to do is we might say, okay, listen state it's gonna be a character type.

[00:05:03] All right, that quiet most of the red squiggly lines for us, except for the fact that you passed it null and you said it was gonna be a character type. So in this case, what we do is we'd say, all right, listen, depending on where we are in fetching the asynchronous code, character type is either going to be or the character that we use in our state is either going to be a character type, or it's going to be null if we haven't loaded it yet.

[00:05:34] And that will work in this case. And it will pass it in. And what's interesting is react is okay with us right now. If we did something like paste and stuff like this, you can see that in this case is no longer okay with us. It's saying, and this is again, this is TypeScript.

[00:05:53] This is actually kind of impressive if you think about it, here It knows that you've checked to see if character exists, which means TypeScript can pretty much confirm that character is non null. And since character can only be null or a character type, and is not null, it must be a character type, right?

[00:06:12] Here on the other hand, you didn't do a check. And so react or TypeScript is rather like, I don't know this is null or character type and this character information card only takes a character type. And so I'm uncomfortable right now, right? And again that TypeScript can vary subtly trying to help you from what, cuz you can see this code technically works, but on a long enough timeline, you could see a world where the code base grows and it grows and it grows.

[00:06:41] And all of a sudden it doesn't work at all. Sweet. So one of the questions is, this promise immediately resolves. What would happen, if it took a little bit of time, the promise is gonna run asynchronously which means this will be null for a little bit longer. For instance, we could theoretically go.

[00:07:07] Let's actually just say, let's cheat a little bit. Let's, we'll simulate a slow network connection. I'll just refresh this completely. Right it will have remained null until that second expires, and it loads. We might choose to do something like add in a loading or something along those lines to put in there as well.

[00:07:47] So we can say something like for instance, we've got a loading component. So we could say, At this point I don't, it's true, Until it's false, right, and so we can at this point will say, all right, fetch the character. Let me actually just give myself some curly braces to buy myself a little more room here.

[00:08:21] And we'll say when it's fetched, the character will also say, set loading to false. And we could show something like As well. And now, we refresh this cuz it's using hot reloading. It's easy loading and then it loads, right? And again, like react or TypeScript just figure it out.

[00:08:53] We're checking to see in this case, is this null or not, it knows the difference and kind of mostly figure out a lot of this for us on our behalf. One of the skills that you might want to train in yourself is, and I say this from personal experience.

[00:09:17] Sometimes again, that's why the kind of some of the fundamental concepts make a little bit of sense here, which is if you don't fully understand the way it works, you're like TypeScript is the problem here. It's making things harder for me, right? And it's mostly trying to help you.

[00:09:29] So let's look at an example where we could see that roughly the same logic, will not work on TypeScript we have, so we'll comment this out for a second. And we'll say, yeah, I'm totally gonna check to see everything. So if it's loading and there's no character, right?

[00:09:57] Then I wanna show the loading component, right? Otherwise, show me the character information with the character being the character, right? And you can see that TypeScript are happy with this, right? And you're like what it just worked before. Like, what's the difference? I don't understand. Like this is ridiculous.

[00:10:29] I'm going to quit programming and start a vegan junk food truck, right? It's not worth it. Well, if we think about it, staring at it for a little bit, we can figure out that, right before we're saying like is there a character, okay if there is a character is not null, right?

[00:10:49] Saying that there is no character doesn't, saying that something doesn't exist doesn't help TypeScript know that it's not null in this case, right? We actually like to say is does this value exists thereby it can't be null cuz this could be all sorts of different things and it doesn't give TypeScript the confidence it needs to know that this won't be null cuz there are edge cases here, right?

[00:11:14] So sometimes worth say anything about, okay what is the logic here am I kind of explaining this attach to you well enough to allow it to help me from bucks right, so kind of flipping some of the logic around like this can. There are cases where this condition can pass in a way that you didn't expect, right?

[00:11:33] So what TypeScript is trying to do is being, listen, I'm a computer. I can run all the probabilities here. There are edge cases here, and things that can happen that will slip through the cracks. So again it is one of those things which is the computer is probably right in this case and just worth before you get upset with it just kind of worth thinking about, okay, am I thinking about this right?