Advanced React Patterns Advanced React Patterns

Flexible Compound Component Q&A

Check out a free preview of the full Advanced React Patterns course:
The "Flexible Compound Component Q&A" Lesson is part of the full, Advanced React Patterns course featured in this preview video. Here's what you'd learn in this lesson:

Kent answers questions from students about nested context providers.

Get Unlimited Access Now

Transcript from the "Flexible Compound Component Q&A" Lesson

>> Kent C. Dodds: Okay, what did you learn?
>> Speaker 2: Throwing an event handler in state just feels so gross to the point where I gave up using context.
>> Kent C. Dodds: Yeah? [CROSSTALK]
>> Speaker 2: Recently because I didn't even think that I could do that. [CROSSTALK] because it feels-
>> Kent C. Dodds: It does feel wrong.

>> Speaker 2: Icky.
>> Kent C. Dodds: Yes, it does.
>> Speaker 2: But it's good to know that, I mean, that's.
>> Kent C. Dodds: That's kind of the accepted way to do this kind of thing.
>> Speaker 2: I guess I should just be on Twitter all the time.
>> Kent C. Dodds: Yeah [LAUGH].
>> Speaker 2: No.
>> Kent C. Dodds: Yeah, that's what I do [LAUGH].

[00:00:38] No, no, so it does feel really kinda weird. If you're concerned about that, there is an alternative actually. You could add a property on state called context or context value, whatever you wanna call it. And then put on is false and toggle this.toggle. And then it's at least nested inside of your state.

>> Speaker 2: And you pass this.state.context?
>> Kent C. Dodds: Yeah so anytime you call setState to update context stuff. When you're doing this, though, you actually have to pass in the whole thing. So you'd say context. And then you'd have to say on is not on and then toggle is this.toggle. Thanks to the way that yeah and something else is busted.

[00:01:27] But, yeah, here we go. state.context [INAUDIBLE]. Something else is busted, but yeah, that's the basic idea, and this extra stuff every single time I call setState to something that's in context is like. And maybe step back and think, okay, so how bad is it really to put handlers, yeah?

>> Speaker 2: Sure, that makes sense. I can see it being useful when you're using a lot of state on this component and then also passing some things down. But in this case it's not.
>> Kent C. Dodds: Yeah, yeah, that's a really great point. So if there's some state you wanna expose to context but you don't wanna expose all of your state, then that would definitely be a solution for that.

[00:02:04] Good question. I'm glad you brought that up. Any other things that you learned, yeah, or questions?
>> Speaker 3: With the new context API, what pattern have you seen like of having multiple contexts and like sort of layering them?
>> Kent C. Dodds: Yeah, yeah, cuz these consumers, they can get kind of nested.

[00:02:23] Like, what if I needed another consumer and another one and another one? Glad you asked. I actually have a pretty active blog. I blog once a week. And not that one, even though that looks like that might be the one. It is, I think it's in answers to common questions, but it might also also be context, the new context API.

[00:02:46] Which is actually not on my blog, I published it to DailyJS. This is where I introduced the context API. And I show, yeah, this is exactly what you're talking about. Andrew was lamenting this. And there is a solution. You can create your own component that does all of that composition for you.

[00:03:09] It handles all the nesting and then your thing is only nested one level. Or there is actually a component called react-composer. There are like six of these now. That can handle all that nesting for you. I think, if we load this up really quick, I can show you what that looks like.

[00:03:27] It is, yeah. So here's the super nested one. It's a lot of fun. Or one that's a little more composed. You can pass in all the providers. Great question. Other things that you learned or questions? So somebody in the chat asked me to reiterate the reason why we're passing this.state to value, rather than an object.

[00:03:55] And so what happens when you pass a, or, here, let's do. I'll just put this in right here. Every single time that this render function is called, this object is gonna be reallocated. So we could assign this to const value = that and pass that. That's functionally equivalent to what we had just a second ago.

[00:04:18] And what this means is we're creating a brand new object in memory and passing it into the value of ToggleContext.Provider. And so whenever ToggleContext.Provider is rendered, it's gonna check, did the value prop change, did the reference change at all? It doesn't do like a shallow compare to the previous or anything like that.

[00:04:41] It's just, did it change. And if it did, then it's going to re-render all of this stuff. Now, as we have it here, the value is going to change every single time. But the actual values within this value will never change. They're always the same. So re-rendering all of the consumers is pointless because those values never change anyway.

[00:05:04] And so that's why we pass this.state in instead. Because the object this.state will only change when state is actually changed.