This course has been updated! We now recommend you take the TypeScript Fundamentals, v3 course.
Transcript from the "Challenge 7: Solution" Lesson
>> Mike North: We're going to look at how to use React with TypeScript to build a stateless functional component. This is a component that has none of its own state. Its job is basically to receive data via props that are passed by whoever's extentiating this component and then provide some nice HTML rendering of whatever it's passed.
[00:00:27] So we're going to first look at our starting point here, we've got the app, the app being rendered by this index.tsx file that's just sort of bootstraps our app. Here we can see if you were to study this, this is a stateful component and this is the next stage that we're gonna tackle after we get through this exercise.
[00:00:49] But what I want you to see is eventually we get the set of results in our render function and if this array of results is of type PlaceDetails. And if we look at PlaceDetails, we can actually say, here I'll give you a little Visual Studio code back flip here.
[00:01:13] We can say Peak Definition. And it'll tell you where this is coming from. Right? I think we can also do, up here we can do Peak type definition. So this is what a PlaceDetails looks like. This seemed to opened up in the middle of my editor. So this I've created to match the json that we expect to get back from the Google Places API that we're hitting.
[00:01:45] We're proxying it through local hosts but that's what we're hitting and that's why you needed that API key. So whenever I'm building one of these simple components that has no state and its job is to render a particular record, as in some visual way on the screen, I typically like to just pass that entire object along so that in the event that I add a new property to that object, I don't really have to go and touch a whole lot of code.
[00:02:16] I've sort of passed it as a unit. And that way, the refactoring is a little bit easier. So I'm gonna get rid of this. This is a sort of our starting point here. And if I were to save, we should see all this stuff disappears on the next refresh and then if I replace it with this, you see that I've got this PlaceDetails value here, so we're taking this array and we're basically turning it into an array of these React components.
[00:02:43] I'm spreading this PlaceDetails out. So each property on this object is being passed as a prop. So the whole collection of props, it aligns with this PlaceDetails interface. That's gonna work out really nicely when we start to define what this component looks like. So if I click in here, well, I can save this.
[00:03:28] This basically will tolerate anything or nothing being passed as props to this object. Instead, I want a little more rigidity.
>> Mike North: So PlaceDetails.
>> Mike North: And let's see if it's smart enough to know, yep. Visual Studio code can even say, I've found something called PlaceDetails. Let's import it from this particular spot, that's slick.
[00:03:58] I saved that. Okay, so now I have some structure and really now this component is basically saying you will get a compile error, TypeScript will object if you try to pass it something other than props that match this shape. So here,
>> Mike North: I'm gonna get a value passed in.
[00:04:21] Now note, we're not destructuring this. A lot of times you end up destructuring props as you receive them in one of these functional components. Keep in mind that the whole set of props themselves conforms to this interface we're interested in. And in this situation, it's really convenient to be able to sort of treat them as an entire object cuz now it's not just little bits of data.
[00:04:46] It's a collection of things and there's some cohesive structure to it. For that matter, I wanna be able to, again, add something to PlaceDetails and later on be able to use it in this component and not have to worry about adding another thing to what I'm destructuring. I'm actually gonna rename this just to pd for ease of use later on.
[00:05:08] So if in here then I did something like this, pd., it is really easy to see the various things that I can use off of this object that's passed in. So I can write the name. And if we refresh, we should see a bunch of donut shops here.
[00:05:26] So we got a lot of extra compile time assurance around this thing to make sure the component right up front says, these are the things I want, pass these to me. We don't have to go around and try to like eyeball a big React component and see where we're pulling something off of this .props.
[00:05:47] In terms of the HTML structure we're looking for, I mentioned that you can use this snapshots thing as guidance. I'm gonna flagrantly rip it off.
>> Mike North: That's correct, let's see.
>> Mike North: Let's try this. Paste.
>> Mike North: And Save and let's see if that works.
>> Mike North: Hey, it looks like it does.
[00:06:17] It's a little horrifyingly spaced out. Let's see if we can clean it up just a little bit.
[00:06:40] So here's our Donut Hut. See, it's like Donut Hut over and over again. Obviously, we have to place our values in here. We will do that in just a moment, once I bring some sanity to this world,
>> Mike North: All right, there's our link and the close, okay, so this looks a little less wacky than it did before.
[00:07:07] And just to make sure it still works, it does, so here we can say I wanna put PlaceDetails, name. And this looks like a map URL, we'll try this one. I think it's URL as opposed to website. Let's see how that works. Okay, it looks like two Donuts Huts, at least we're seeing some other stuff here.
[00:07:33] The addresses are all the same, that's cuz that's still hardcoded.
>> Mike North: Vicinity seems like an addressy thing. Okay, now things are starting to look a little different. This URL here, I think that's the website field.
>> Mike North: Now, we might get a situation where we have something that doesn't have a website.
>> Mike North: Let's make sure, there's a restaurant here. I think that's the icon field. We should be able to see some other icons.
>> Mike North: Although, in this particular scenario, I don't believe we'll see anything other than donut shops, we could change this search term here from donut to bank and see different icons.
[00:08:33] Okay, so now we're sort of at a point where we have some reasonable search results here. So if you're taking stuff away from this, just from this first step here, number one, know that when we were defining our stateless functional component with React, we have an interface. So anyone who's looking at this knows exactly what they need to pass.
[00:08:54] And if we were to leave this out, we would get an objection from TypeScript. Yes?
>> Speaker 2: Yeah, I interrupt you here cuz this is where my question is. So what is the effective difference between? Cuz you saw my code. I put the interface to describe the params that are passed in, so after the PD, there are your arguments.
>> Mike North: Like this?
>> Speaker 2: Yeah.
>> Mike North: Right. So what's happening here is
>> Speaker 2: It still had the NA after the FSC, I still got all the completion and whatnot.
>> Mike North: This is what you had.
>> Speaker 2: Yes.
>> Mike North: So I actually want you kind of pay attention to this here.
[00:09:36] So this is what you had. This is TypeScript saying well, I can make no guarantees that things will line up. This here is you saying tolerate anything. And let me prove it to you. Remember when we spread and object, we can add other properties. I can put this here and I get no objections from TypeScript.
[00:10:05] So in essence, what you're effectively doing there, it is similar to casting. If we have this here, we're basically saying in terms of the type of PlaceSearchResult that we're exporting, we're saying here that you can give me whatever you want as props, whatever you want. You'll get no complaints.
[00:10:28] Anything or nothing, they're all assigned, they’re all assignable to an any. And then here you’re saying, because you have that great flexibility, you can then here say, okay, well, now, let’s treat this object as a PlaceDetails type. And you’re going to use it that way. But I could do something like this and cause some problems where basically TypeScript has found it has not protected you from this situation here.
[00:10:59] Right? So I did not get that enforcement from the TypeScript compiler saying you've gotta give me what I'm asking for, cuz here you're saying I'm asking for anything. Does that make sense? It's almost like casting. So that's why we do it this way. Whereas in this situation here, if we tried those shenanigans,
>> Mike North: like this
>> Mike North: It's gonna say this object here, name = 'foo' is not assignable to type PlaceDetails. It's flat out telling you, you gave me this. I need that. I can't make these line up, and this is super actionable. You, as a developer say, well wait, clearly I need to look at what PlaceDetails the shape is.
[00:11:52] And we need to line up with that. Because until I do that, this thing is gonna keep yelling at me. So this is why I wanted to spend some time working with react today. Because like this, I love this about working with type script and react together. Because now you really, you can catch so many things.
[00:12:12] At compile time that had a tendency to be stuff that you really need a thorough code review for in order to get assurance about that. And now, we just basically, in code reviews, have to look for stuff like this and recognize that, you're being overly tolerant here. You're saying you're okay with anything, but clearly the code below is not.
>> Mike North: So that is PlaceDetails. And that it state its functional components.