Advanced React Patterns Basic Compound Component Solution
This course still contains valuable patterns in React, but doesn't cover React Hooks introduced in React 1.16.
Transcript from the "Basic Compound Component Solution" Lesson
>> Kent C. Dodds: Already, so how is that exercise? Some people seem to find a little bit of a challenge. Hopefully, this walk through will help entering a questions that you may have had. So I'll go ahead and start off the test. [COUGH] By the way, while I'm going, once I've got myself, like I finished everything that I was working on.
[00:00:21] I actually do a get reset hard, so that I'm back to a clean state. You don't need to, like these exercises don't build on each other from the source code standpoint, and so, yeah. Just to make sure we're all on the same page. That's what I'm doing, so you can feel free to do that if you'd like.
[00:00:38] Okay so I'll just make sure we're running the number two test. And let's take a look at the solution. So first I'll go ahead and build these compound components, the children components here. And so we have a static on, and that's an arrow function component. And it's going to accept some props, and it'll say props.on.
[00:01:04] If it is on, then we'll return the props.children. Otherwise, we'll return null.
>> Kent C. Dodds: Okay, we'll do the same for off except in the reverse. So if it is off then we'll return null, otherwise will return nothing or, sorry, yeah, I think you know what I mean by reading my code.
[00:01:28] So, [LAUGH] and then, we´ll have the button, and that will be a little bit different. Just gonna take this switch, bring it up here instead. And will accept on as a prop, well it accept toggle as a prop. And we don't children for this one.
>> Kent C. Dodds: Cool, and so now comes the part that's a little bit more challenging And that is using these two utility methods from React.
[00:02:02] So, I'm gonna go ahead and comment this out. And then we'll return React.Children.map, this.props.children so this is the thing we wanna map. And this is how we want to map those. And that will be return React.cloneElement, here and actually I'll just call this child element. This are react elements that we're cloning.
[00:02:32] And we're gonna clone it with some extra props.
>> Kent C. Dodds: And those props will be on this.state.on and toggle this.toggle. So this clone element is responsible for passing these compound components, the props that they need to do their job. But what's cool is that all of this is happening under the hood.
[00:02:54] From a user standpoint, they don't need to know that's what's going on. They just use these components, and we promise that they'll work together properly. So if I save that, our tests are passing. And if we pop open the example, then we get the exercise is working or the rendered version is working as well.
>> Kent C. Dodds: Okay, what questions do you all have about this? Yeah?
>> Speaker 2: For on and off, you used the expression. Could those be just binary, like If-
>> Speaker 2: On is false E, or yeah, if on is false E, then render off props.children for off, if one is truth E then render props.children.
[00:03:36] So just a double apersand as opposed-
>> Kent C. Dodds: I see what you mean, yeah, yes. So this is pretty common to do, and I'm glad that you asked, cuz I see this all the time. So, this is fine, in this case. One time when this is tripped me up, is, if I have like a list.links.
[00:04:20] And this user had no contacts, and so I just had a little zero right there, there was nothing, just a little zero sitting in a middle of nowhere. Because this is something that we did. So that's why I pretty much, if I'm going to do this, then what I'll do is I'll say boolean.
[00:04:37] And then when this returns false I won´t render. But that´s like implementation detail of React, so I actually prefer to be more explicit which is why I use the .Save California Water Program Inhouse. So I´m definitely going to render something, and I´m gonna choose what renders. Good, I'm glad you asked that question, that's pretty common.
[00:04:58] [INAUDIBLE] Other questions? Anything from the chat?
>> Speaker 3: I just threw a span inside the toggle element, and that works, and my question is why Save California Water Program Inhouse. React.Children.maps seems to handle that just fine.
>> Kent C. Dodds: You threw a spam right here?
>> Speaker 3: No, sorry, just like inside of, in a usage.
>> Kent C. Dodds: In the usage.
>> Speaker 3: I kow, I'm not suppose to touch it but.
>> Kent C. Dodds: Right here?
>> Speaker 3: Yeah.
>> Kent C. Dodds: Like that?
>> Speaker 3: Just as simpling up [CROSSTALK].
>> Kent C. Dodds: I see, I see, yeah.
>> Speaker 3: Yeah, I was just curious what was happening.
>> Kent C. Dodds: Yeah, So let's actually take a look at that.
[00:05:37] You actually see the warning right there, but you can see it in the browser as well. It's going to say hey, you passed on a non-boolean attribute of on to a span. And so what's happening here is this is also a react element. A react element that renders a we're passing props on a title to this span.
[00:06:01] So, it would be like on equals hi, there, whatever. On is not a property that span can accept. So, I wouldn't do that and we'll actually, there are ways that you can around that problem, actually, I can talk about that. But that's what's happening. So it works, but you get this warning because it's passing a non-dom attribute to this dom-note.
[00:06:23] So with that you can get around that, is add a little check in here that says, if it's one of my static components, then don't clone the elem ent. And so you can make it a static compound components equals this array toggle not on and so on and so forth.
[00:06:46] And then you check is it in there? If it's not, then I won't clone it. Good question, yeah.
>> Speaker 2: I think a point of confusion for me was when I was cloning the element and then passing this dot toggle into the child. As oppose to using the start toggle within the static button.
[00:07:04] That threw me for a second.
>> Kent C. Dodds: So you, just to make sure I understand.
>> Speaker 2: On-click for the button, I've used this dot toggle as oppose to passing it in the prompt.
>> Kent C. Dodds: I see what you're saying ,yeah. And did that work?
>> Kent C. Dodds: It wouldn't have worked.
>> Speaker 2: No.
>> Kent C. Dodds: I'd be surprised if it worked. So the reason it wouldn't work is because this is a static property, you have no instant or access to the instance. So you could make it work like this, except then you wouldn't be able to use those down here. So actually [INAUDIBLE].
[00:07:37] So, that's why you have to accept it as props. What's cool about this is it's all implicit. So, maybe it complicates the implementation a tiny bit, but that's in favor of the users of our component.
>> Speaker 3: You said, you wouldn't be able to use. Those elements in the render, if they weren't static, can you just tackle a little more about it?
>> Kent C. Dodds: Yeah, sure, so if I remove this static property, now these are instance property. So I can reference it like this.on, but if I reference it off of the class. They're actually not properties of the class.
>> Speaker 3: Right.
>> Kent C. Dodds: When they're not static, and so, I'm using it right here I'm actually referencing it off of the class.
[00:08:22] That make sense?
>> Speaker 3: Yes.
>> Kent C. Dodds: Cool, I should also mention there's actually nothing sacred about putting these on the class as stag properties. You could just as easily take these and move them up here. And then instead of static, const, and then use those like that. If I'm gonna do compound components, I like to make it a static property on the class, just to make the relationship more explicit.
[00:08:51] Just as a communication device to those who are using the code and looking at the code later. But yeah, there is nothing you absolutely have to do. So your question on chat?
>> Speaker 4: Can you use a read out map instead of React.Children.Map?
>> Kent C. Dodds: Yeah, that's a great question, you'll restore things back to order here.
[00:09:11] So we could use this .props.children.map, and that would actually work in our case, unless there was only one child. So React actually, when you have one child, children is assigned to that element rather than an array of those elements. If you're using Preact, it actually will always be an array.
[00:09:34] But in React, it can be just the one element if there's only one, which is why React.Children.map exist. I remember once looking into the source code for React.Children.map and I was like, it will just be simple like if it's in the right then. No, it's not, I honestly, I don't know what it does It was like a lot bigger than I expected.
[00:09:56] So that might be a fun exercise for you to go in later and figure out what on Earth does this method is doing. Because I don't know, I didn't take more time to look into it. So, hopefully that answers your question. Does anyone else have Have questions.
>> Kent C. Dodds: Okay, cool.
[00:10:20] Let us move onto our next. Sorry, woo, that was a close call. Let's go ahead and submit our feedback and elaboration. So you can reiterate the things that you learned. Make sure that you retain those things, and then we'll move on to the next exercise. What were some of the things that you wrote in your elaboration and [INAUDIBLE]?
[00:10:42] What did you learn?
>> Kent C. Dodds: As a recap for all of us, yeah?
>> Speaker 5: I never knew about Children.map or cloneElement, so it's cool.
>> Kent C. Dodds: Nice, yeah, so this is like, literally the only time I've ever used these methods. [LAUGH] So in down shift, we could use a reactive specific method like that but it supports pre-active as well.
[00:11:08] And so I just wrote my own little like, two-liner. So yeah, I don't even use it in downshift. But it is, there are handful of those React.Children utilities that can go check out, they can be kinda handy sometimes