This course still contains valuable patterns in React, but doesn't cover React Hooks introduced in React 1.16.

Check out a free preview of the full Advanced React Patterns course:
The "Provider Pattern Solution" 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 walks through the Provider Pattern Exercise by using the React createContext API to make state and helpers available anywhere in the React tree.

Get Unlimited Access Now

Transcript from the "Provider Pattern Solution" Lesson

>> Kent C. Dodds: Awesome. So, let's go ahead and get this going. We'll npm t to run the tests. Toggle those back so we get our failing test. Okay, so the first thing we see is this.props.children is not a function. That's because our new usage is not using the render prop API.

[00:00:21] We'll start out by switching this to just the provider pattern, and then I'll add the render prop API back so we can do both, which is kinda fun. The first thing that we need to do is we're gonna create context so we can tunnel some of our state and helpers through the React tree and have it pop out anywhere else within the React tree.

[00:00:45] So we'll say ToggleContext = React.createContext. And this is gonna have on as false and toggle is, actually, let's just pull this thing up. This thing, tada. Okay, so this is gonna be back to on is false. And these will all just be noop functions.
>> Kent C. Dodds: Okay, and then now that we have that, let's go ahead and expose the consumer so that when we export this toggle component people can just use it off of the toggle.

[00:01:30] So we'll say static Consumer = ToggleContext,Consumer. And then we need, because we don't want to have unnecessary rerenders like we talked about when we were doing compound components, we're going to stick all of our state and helpers right inside of our initial state. Which our state will get initialized to.

[00:01:58] So let's see, it's right around here, do, and yeah, that's good. From there
>> Kent C. Dodds: Rather than this.getStateAndHelpers, we're just gonna this.state, because that is now StateAndHelpers. And all of these functions right here need to be moved above the initial state so that they can be referenced as they are.

[00:02:38] Just order of operations thing. Pretend this is a constructor function. That's sort of how it works. Okay, cool. And then we can actually remove getStateAndHelpers because we're no longer using it anywhere. Well, we're about to remove it from here. So we'll return the toggleContext.provider, where the value is this.state.

[00:03:04] And then we'll have this.props.children. And then everything works wonderfully. We have, anywhere inside of our tree underneath this toggle component we can use the Toggle.Consumer to get the toggle state and helpers. The value from toggle. So our NavSwitch doesn't have to accept any props. It can just use the toggle consumer anywhere it wants.

[00:03:35] The header doesn't have to forward any props onto these two things, cuz it doesn't care about those props. So that is the utility of the provider pattern. So I'm gonna make this work with both render props and regular children. But before I do that, does anybody have questions?

>> Kent C. Dodds: Yeah.
>> Speaker 2: Why did anyone use React before new context API? It's so good.
>> Kent C. Dodds: Yeah, yeah. Well, React was pretty dang good without it. But yeah, the new context API simplifies it a ton. I can show you the alternative solution with the old context API right now if you want.

[00:04:20] So, advanced React patterns. So there's a reason that this is a v2. My v1 was actually for Egghead. But here's the provider pattern with v1. Start search here, you have this. Yeah, so I had a whole separate component that was the provider. And it did all this wonky stuff.

[00:04:44] Yeah, I don't even wanna.
>> Speaker 2: [LAUGH]
>> Kent C. Dodds: Like it was not as good. And it used React, well, let's see, broadcast. Yeah. So this solution didn't even work. If you had a shouldComponentUpdate false anywhere in the tree, then any of the consumers wouldn't be able to get updates, and so you had to use this React broadcast thing right here.

[00:05:08] Which was no fun. It was just like, React broadcast was actually similar to the new context API in some ways. And so it actually significantly simplified many things. But still, the new context API is like miles simpler than the old one. Any other observations or questions? All right, so let's make this support both, just for fun.

[00:05:36] So what we're going to do is we'll say, let's see, we'll call this ui. And we'll say this.props.children, we'll just type up that thing. If it's a function, then we'll call this.props.children with this.state. Otherwise, it'll be this.props.children.
>> Kent C. Dodds: And then we render our UI. And now it actually supports both.

[00:06:05] That was pretty handy, right? Cool stuff. So now our component, what's nice about this is it's flexible enough to be as simple as possible, like the simplest. It supports all the way back to the initial use case when we started with render props. And now it supports all the way down to the provider pattern and supporting providing our state anywhere in the tree.

[00:06:33] It's pretty cool.
>> Kent C. Dodds: All righty, so shall we continue on to our last pattern of the day? It's not the last exercise, but the last one, the last pattern. All right, cool. Anybody wanna share anything that they filled out in their elaboration, what you learned? That React wasn't usable before the new context API.

[00:07:00] That was one thing. No, just kidding. But it is nice. It is really nice.
>> Speaker 2: Only exposing the consumer in like 99% of cases.
>> Kent C. Dodds: Yeah.
>> Speaker 2: That makes sense.
>> Kent C. Dodds: Yeah, I think generally. I mean, there are some use cases where the provider is nice. But I kind of like to keep the provider used in the root component that's doing all the state management stuff anyway and then only exposing the consumer.

[00:07:26] And then making it a static property, I think, kind of helps associate it better, so.