React and TypeScript Reusable Props Interface
This course has been updated! We now recommend you take the React and TypeScript, v2 course.
Transcript from the "Reusable Props Interface" Lesson
>> We still have to, TypeScript's gonna be angry with us. And what we're gonna need to do for the next little bit is to make TypeScript less mad at us. So, first thing that it is mad at us about is, well color swatch doesn't need anything anymore. Color sliders also doesn't need anything any more, either I'll comment out the inputs for now, we'll get to those in a second.
[00:00:25] But we still have this problem that I just kinda hand waved to and ignored there for a second there, which is, okay. Yeah, no, I'm not okay with this. Because we don't know what it's gonna be. So we could say that listen, we can do it, we didn't sell this the same way we solved with some of that state, you state stuff before.
[00:00:42] We can say listen, yeah, it can either be the RGBContextType or it can be null. Look, everything's mostly okay, here, right now. But not everywhere, because now it doesn't know if these properties exist on this object, right? Because if you're trying to pull red, green and blue off of null, you're gonna crash, and TypeScript doesn't know how to save you from yourself in this case, right?
[00:01:49] ?.blue, which is basically, if value exists, then pull the blue property off of it, right? And if you swapped out everything in your code base to use value, ?.blue, you would appease TypeScript, because all TypeScript is trying to say is, I cannot promise you that it's not null.
[00:02:32] My argument to you is just going to be don't, right? And so that's where we have some other options here, to have TypeScript be less angry. Because to be clear, TypeScript's not wrong. Many of us have been caught by bugs just as insidious where it's, such and such is not a property on undefined, right?
[00:03:21] I understand what you think is a type system, but this is a situation where I know better, and just trust me. So we could say here's an empty object. And we're gonna say but just pretend that it's an RGB context type, right? And because the default value is now an empty object, calling those properties is not problematic.
[00:03:44] It's not gonna blow up, they'll just be undefined, which could be problematic in your code base. But really, we know that this is effectively set on the next line, right? We are confident, we, in this case, find it within our power to override type scripts like built-in mechanisms, cuz we know what we're doing.
[00:04:07] Another place where you might find yourself using this is in that character cards that we had earlier. The alignment when only ever good or bad, but TypeScript is assumed that it was a string. And so if you pulled it from an API, TypeScript might not be able to know that.
[00:04:46] So we know in case it's happening. There is a third way to do this. I'll kinda just tell you what it is now, but we need to know a few more things before we can implement it without you just staring at me, yeah, great, he's writing complete gibberish.
[00:05:03] But the other way is to kind of create an abstraction that will, in the same way we had to check to see if value was null or not. We could create our own useContext that checks to see if it's defined before it lets us use anything, and just take all those checks and put it in one place.
[00:05:16] That is arguably the correct answer. To be clear, this is what we do, we know in this case. If you didn't need dispatch, you could say you can even define a green, red, green and blue value here, and only put in dispatch lane. There's lots of ways to handle this.
[00:05:38] Generally speaking, I think that this will do the trick most of the time but understand you're taking on a certain amount of risk. So yeah, that is some of the problems that come with the fact that a lot of the safety and benefits here are really good. But we are ultimately building on top of a language and platform that wasn't always immediately there for this.
[00:06:01] So one of the things the problem we have to solve for, and again the very beginning of this course, right? Yeah, just say that your strings are gonna be strings, everything's great. Where are the pain points with React and TypeScript start to come along is when you start to do some of the more advanced React patterns.
[00:06:20] Cuz like most things, the easy things are easy, and the weird cases are when you try to do some things that are a little bit trickier, all right? So if we look, our color sliders and our color inputs are roughly the same. We're just basically using, we're defaulting to the built-in HTML elements.
[00:06:44] So this is an input with the type range this one, the color slider, this is one, yeah, type range. And then the color input is just a regular type number, right? But other than that they're mostly the same other, than some formatting and stuff that. It'd be great and then the sliders floor I'll just create the red, green and blue for each.
[00:07:07] I'll show them to you real quick. So color sliders, yeah, it's just three of them, color inputs is roughly the same thing. Would it be nice if I could just use them kind of interchangeably? And one of the things that we can notice is that previously, the sliders we took over the individual side was actually still to this moment.
[00:07:30] Take ID label and value, we're gonna need an on change in there as well, the inputs right now don't do anything. And the slider, it is id label value and then the on change that we're gonna put in both places. It'd be great if I could create an abstraction here, right?
[00:07:50] I would love to just be able to say hey, they take roughly the same props, or in a few minutes exactly the same props. Wouldn't it be nice to simply define, okay, here's the props that I'm expecting that are kind of similar to both of them. And just say like, all right, for you, I wanna say here's the color input component, make me the three of them wire them up.
[00:08:15] For you, color sliders, do the same. So one might think, no, I had to specifically type everything, there's no way that I can be dynamic with what component I pass in and have it conditionally rendered, right? All right, so let's, let's take a look at the next one that I wanted to show you which is that's the wrong one.
[00:08:28] Not right? So let's make a new one called color adjustment. And so okay, we're gonna have an interface here. It could be a type, and this is gonna be our AdjustmentinputProps. And what [INAUDIBLE] id is gonna be a string. A label is going to be a string, Value will be a number, and then on change.
[00:09:02] Is going to be an event, and we know that it's gonna be a change event from HTML input elements. Luckily, they're both HTML input elements. And that's going to return void, so we have this common type now. And what we're gonna say is listen, you can pass me in any component that you want as long as it adheres to this interface.
[00:09:29] You wanna use this color input, fine. You wanna use a color slider? As long as you pass in a component to this corner we're building right now that adheres to this interface, we'll be able to work with it dynamically. So then, the props for rendering, the three will be an interface, color adjustment props, just like we've seen before.
[00:09:52] And again, this is really gonna take one thing which is, what component that I want to render. And I'm using capital A cuz I'm gonna talk about a React component. And so, this is one that we'll use, called React. We're gonna talk about these in a second a little bit more.
[00:10:08] I'm just kinda introducing the topic now of what we call utility types. So React.ComponentType is, Saying, okay, I got pull in react, hold on. Input. From react and then adjust it, let's go with adjustment. I like that one, better, what we're gonna say is the type of the prop that we're expecting.
[00:10:44] Previously, we've seen string, number, boolean. Some objects, we're gonna say is, the adjustment prop on this component can be any component that adheres to these properties up here. All right, so as long as we pass in something, a component that has the same interface, we can pass it in dynamically.
[00:11:06] So let's actually just grab, I'm gonna grab the color sliders. Real quick, and I'm gonna reuse most of this code. So we'll just grab that and paste it in. And at this point, we do need to pull in react.use.context. And we'll import RGB context as well. Context, sweet, the only thing that's blowing up right now is I haven't pulled in the color component cuz we don't actually wanna use the color slider yet.
[00:11:53] What we want to do is whatever adjustment has been passed in. So we know that the only prop that this takes is adjustment. And here we'll say, Yeah, that's just our color adjustment props. And then we can swap it out saying whatever component is passed in, instead of rendering three color sliders, do whatever component was passed in.
[00:12:25] Right, so this works, we just need to use it, so we can kind of swap it out. So go into application and we're gonna say is instead of color sliders we're gonna say color. Yep, wait for it, Import color adjustment, Color adjustment, the values are in red, that's fine.
[00:12:59] But yeah, my suspicion when autocomplete didn't work is that I didn't export it. Or I called it, All right, that should work now. So we've got color adjustment, and now we can basically say all right, instead of saying color sliders plural, what I want you to be is a color slider.
[00:13:25] I'm sorry, ColorAdjustment. And the adjustment component is gonna be a singular color slider. All right, and then we can go ahead, we put more of those in there. I can also change this to a color, Input, and it will render both of them. So now, I can just make changes to this one kinda higher order-ish component, and, it's not hard coded as you can only have stuff to put in anything that confirms.
[00:14:04] To this adjustment input props will work and we can start dynamically passing in react components. Well, as we just need to figure out what React gives us in this case as well. And so that came from the utility type of React.component type.