Check out a free preview of the full Complete Intro to React, v8 course:
The "Component Composition" Lesson is part of the full, Complete Intro to React, v8 course featured in this preview video. Here's what you'd learn in this lesson:

Brian demonstrates how to create reusable organized code by taking large components and breaking them down into smaller components.

Get Unlimited Access Now

Transcript from the "Component Composition" Lesson

[00:00:00]
>> Okay, so that was just handling user input. That's fine. We're all done with that. Let's go onto component composition. So just kind of like a rule of thumb, something like this where I'm rendering out a pet in a list of them. This is a good kind of place where it makes sense.

[00:00:21] Maybe I should extract in a component out of this. Like, for example, this results thing where I have a list of pets and that renders out like a bunch of pet components, that could be reusable, right? I could use that here in the results page. I could use that in an admin page where I'm just showing a list of pets.

[00:00:40] Basically, it's something that you give it a list of pets and it displays a bunch of nice looking pets for you. That seems like it's kind of a good candidate for a reusable component, right? So I'm trying to help you figure out when should I pull things out and make them their own component.

[00:00:57] When something should be individually testable, or individually usable, or if something's just getting too big, like this search params page, like 90 lines. That's pretty long for a React component. I'm not gonna give you any sort of ceiling, but if you have a 300 line or a 500 line React component, it's probably too long.

[00:01:20] There's probably candidates in there for stuff for you to pull out. Smaller, single purpose components are easier to read, they're easier to understand, and when you can do it, you should do it. Even if it's not reusable, smaller things are easier to understand, easier to wrap your mind around, easier to share.

[00:01:39] So, this is a good thing here. So we're gonna pull this out and we're gonna make a results page. So I'm gonna make a new file here, put in my source directory, and it's gonna be called Results.jsx. It's gonna import Pet from ./Pet. Const results, all it's gonna do is it's gonna take in the props, and I'm gonna pull out the pets part of the props.

[00:02:09] That's what this is. This is just destructuring. I'm getting, this is expecting a prop called pets, and it's gonna pull that out. So that's what this is. This is going to return a div with the className = search. And if there's no pets length, yeah, pets has no length.

[00:02:37] So we're gonna do what's called the ternary. So if I have an array of length zero, it's just gonna say in an h1, No Pets Found. Otherwise, It's gonna do pets.map. And this is gonna be a pet component, and then we're just gonna give it all of our things.

[00:03:11] Now, I'm gonna show you a little thing that you'll see, and I don't want you to do it, but I'm gonna show you how to do it, ...pet. And then, you'll need a key. So key=(pet.id) I don't like this, but it works. So let's talk about what it is, and why I think you should do it the other way.

[00:03:37] This is called the spread operator, which is it's not precisely the same as the JavaScript one, but you can think of it as functionally equivalent. You're basically saying that I have a bag of properties here inside of pet. I want you to spread them out over as if I had done animal = pet.animal, key = pet.id, name = pet.name, breed = pet.breed, right?

[00:04:05] All of those individually, you're just saying spread this out, which is actually literally what we're about to do. So why don't I like this? It's very implicit. You're basically saying pass everything along. Do I want to pass everything along? I don't know. Maybe today I do, but tomorrow, maybe we're gonna add more things from the API.

[00:04:27] This is better to be explicit that this component expects these things, and therefore, is receiving these things. Cuz sometimes you'll be looking at the processes like where the hell did this come from, right? And if you're just doing the spread operator everywhere, I think there's some performance implication, but who cares?

[00:04:45] What's more important here is that you're being explicit like, the pet component expects this, therefore, I am giving the pet component this, right? It makes the contractor explicit. The reason why I show that to you is you're never really gonna end up at a company where someone thinks it's a good idea.

[00:05:03] And you're gonna go up just like, I know that this is a bad idea and that you are full of crap. Cuz that is how to be a good co-worker. [LAUGH] Someone's looking at this like, I'd never wanna work with Brian. That's probably smart. images=pet.images. Okay, so one thing I will say where is appropriate to do what I told you not to.

[00:05:35] If you have a component that is meant to be a total pass through component where it's not meant to do anything. All it's meant to do is take in something and then apply some effect and pass it onward, and it doesn't actually need to know anything about that.

[00:05:50] By all means, use the spread operator, right? Cuz you're basically explicitly saying this component does not care what's passing through it. That is totally okay. And by the way, if you ever use TypeScript, which you will in intermediate React, you have to do it this way, anyway. So it's just good to get in that habit because everyone's using TypeScript these days.

[00:06:14] All right, location pet.city, pet.state. Okay, and then, down here at the bottom, make sure as always you export results, export default Results. Cool, search params, come back here where you had this pets thing here, put Results, and we have to pass it in pets, right? So I deleted that pets.map business from search.params and I passed in pets here.

[00:07:03] And then you can get rid of pet up here, cuz we're not using that directly in search params anymore, and then make sure you're importing results from results, okay? So, if we have done our job correctly, it should look something like this. The reason why it's styled differently is we gave it a div with the search class, which gave it some style.

[00:07:26] And now if I put some random stuff in here and submit, you'll get a No Pets Found, which is a nice way of letting a user know. I wouldn't search for it, I didn't find anything. This is what you get. I know some of you are also thinking like, location doesn't work super well.

[00:07:43] That's because it doesn't. It's just doing some basic pattern matching. I did not put elastic search here or anything like that. So just be aware that even though you're searching for Seattle, Washington, it's just doing basically text search.