Advanced React Patterns Render Prop Q&A
This course still contains valuable patterns in React, but doesn't cover React Hooks introduced in React 1.16.
Transcript from the "Render Prop Q&A" Lesson
>> Kent C. Dodds: So what questions do you have about render props? I know some people who were asking in the chat about, how does this compare to higher order components and stuff, we'll get to those eventually for sure. But what other questions are there?
>> Kent C. Dodds: Yeah?
>> Speaker 2: I asked if there's still the re-render issue.
>> Kent C. Dodds: Right, thank you for asking that. So with the compound components, I talked about how if you set the value equal to an object that you declare every single time, it's gonna re-render all the consumers over, and over, and over again. So this is not quite the same because we're calling children every single time.
[00:00:42] So before we did all of that rewrite, that render function's always gonna run. We could stick all of this stuff directly in here, it'll return that stuff, whatever. And that would be functionally equivalent to what we have now. There's no way to avoid rendering the children in this case.
[00:01:02] In addition, what is really controlling whether or not this thing is gonna re-render is if its state updates anyway. So yeah, you don't really run into the same problem. You actually want the render method to be called every single time in this case.
>> Kent C. Dodds: Any other questions? Yeah?
>> Speaker 3: You could do the same pattern with a single pure functional child, right? You stuck up your functional reactant component as a child there, it would receive-
>> Kent C. Dodds: I see what you mean, yeah, yeah, good question. So this is actually something we're not going to cover in the workshop today.
[00:01:50] This is called component injection. And I don’t teach it because I think render props are better. Even though Donovan from American Express will be upset at me for that.
>> Group: [LAUGH]
>> Kent C. Dodds: So we can have toggle child, and then this thing could, or actually [INAUDIBLE]. I could have done this a little bit better.
>> Kent C. Dodds: Something like that. And then you could stick toggle child in there, and that'll work as well. So the couple of differences here, because this is, and actually what's cool about this is we could actually make this a legit React.Component. It could have life cycle methods, all that stuff.
[00:02:34] But the reason that I, yeah, the reason that I generally, okay, sorry, let me take a step back. You can only do this, this is only halfway to component injection, because this ToggleChild, it's a function and it's being called directly like this. For you to actually mount that component, you would have to do return React.createElement( this.props.children), and then pass the props that you want, so all this stuff.
[00:03:09] And now that is component injection. And that should work just as well. And now this would have access to default props and all the life cycle methods and stuff. The reason I prefer the render prop over component injection is because the render prop is more powerful, and when you would call create element, it adds a whole other layer of nesting in my react tree, and often I don't care enough to give this thing a name.
[00:03:41] Like, clearly this is the render child because I'm rendering, or the ToggleChild because it's the child of the toggle. Why do I need to give that a name? And so that wouldn't be enough for me to prefer render props over a component injection. But what really seals the deal for me is, I could just say, props and props.
[00:04:06] And now I get all the benefits of component injection without actually having to use component injection. So as a user, you're pushing that onto the user to be able to use life cycle methods. But I feel like that's pretty straightforward and so if I'm only gonna do one, I'm just gonna do the the Render Props.
[00:04:29] Now you could also say, hey, if you want to use life cycle methods, you can, and then in your render method, you check, is this a React component class? And if it is, then I'll createElement otherwise I'll call the function. So there's a lot of flexibility you can have in there.
[00:04:44] But I'll just do a Render Prop. It makes the API a lot simpler. Glad you asked that though, so we could cover that. Other questions or observations? Yeah?
>> Speaker 5: It seems that a render or, if we were to compare and contrast a compound components versus render properties, it seems that the compound component is doing a lot of the same things, but it's holding a little more control, and a render prop is giving complete control back up to whoever is implementing it.
[00:05:24] So when would you use one or the other in your applications?
>> Kent C. Dodds: Yeah, that's a great question. So if we look at the usage example here with compound components, you don't actually see what the state is that's being shared with toggle and all of its children. Aall the state and the handlers, everything is totally implicit.
[00:05:50] And so if you have a situation like that where people don't really care what those values are, it's not really useful to them, one example might be an accordion. You have several accordion compound components and then the user clicks on one. There's some inputs that state that's gonna be set between the parents that determines which index is open and the children that says, I'm the index that's open so I'm gonna open up.
[00:06:21] And the user of that component doesn't really need to know which one is open, they're just like, here's my accordion, here's my accordion title, and here are the contents of that accordion. And they don't really care. And so adding that additional layer of complexity where they have to say, if accordion index one is open, then I'm gonna render this thing.
[00:06:43] It's just extra work for the end user. Whereas some really highly, or some components that need that very fine detail on and control over how things are rendered, render prop fits a lot better. The really cool thing about render props is that you could implement your base component as a render prop and then a compound component on top of that.
[00:07:07] And so all the logic and everything lives inside the render prop component. And then you're like, well, this is a really common case. I'll build a compound component on top of that. Then most people can use a compound component, and if they need the extra stuff, then they can use the render prop component.
[00:07:21] So I haven't yet found the a pattern that is lower level than render props with regard to sharing logic. Just really, really great way to do that and then you can build on top.
>> Kent C. Dodds: Good question. Other questions? Observations?
>> Kent C. Dodds: All right, sweet.
>> Speaker 6: There's one in the chatroom.
>> Kent C. Dodds: One in chat, sweet. Is there any difference between passing a render function as a prop and a render function as children? Good question, this is actually a pretty common question. And with that, I've got this common questions about render props, and I don't think that this is one of the ones I mentioned, but there are a couple others.
[00:08:02] You can check my blog later for that. But yeah, so the question is, what if instead it's render? So what I could do is I would simply take this thing and say, render equals that thing. And that's functionally equivalent. So why choose one over the other? The biggest reason that I chose children over render as a prop name is because that's what context API does, it uses children for the render prop.
[00:08:34] And so I like consistency, and so that's what I am gonna go with. There are a couple of reasons that I like children over render, but that's the biggest one. One of the other reasons is if I have a render prop that's really long, in fact, let's just pull this back in here.
[00:08:47] Let's see. Just to illustrate this.
>> Kent C. Dodds: We'll do on and toggle, okay. So I've got a relatively long render prop, and sometimes these will be very, very long. So you have your on toggle, you have your render, and that's it right. Well, you have to scroll down all the way down here and say, veryImportantProp = true.
[00:09:15] Okay, now when I'm looking at this, I think that these are the only props that my component's using. But I missed this very important prop. If you use children for the name of the prop, then that's not possible because what comes after children? Nothing, just like the closing tag.
[00:09:31] And that's the other reason that I prefer using render prop, or a render called children rather than the render function, is
>> Kent C. Dodds: It's easier for me to see at what point does toggle start and end.
>> Kent C. Dodds: So those are some of the reasons I prefer that. Children.
>> Kent C. Dodds: We good?
[00:10:03] Was that fun? Is this the type of component you're gonna write and it will a smile on your face? Well I'm seeing smiles now, that's good enough for me. Okay, so go ahead and jump in the test, submit your elaboration, what did you learn and then we'll talk about that for a second and jump into the next one.