Check out a free preview of the full A Tour of JavaScript & React Patterns course

The "Provider Pattern" Lesson is part of the full, A Tour of JavaScript & React Patterns course featured in this preview video. Here's what you'd learn in this lesson:

Lydia explains how the provider pattern uses React's Context API to share data between components. This eliminates the need to "prop drill", or pass props from parent-to-child anytime a shared context is required. Components will re-render whenever a value changes so developers will want to be careful which components are consuming the context.


Transcript from the "Provider Pattern" Lesson

>> So if you wanna share stateful logic throughout your application using Hooks, you can use the Provider Pattern. And this is kind of a combination between the context API and. Well, you don't have to use Hooks but we'll see later that that's definitely an extra. So with a Provider Pattern we can say or for example we have like this site again and we wanna have like a dark mode and a light mode.

So all the components on that website need to know, okay, what's the current theme, it needs to get that data from somewhere. Now usually, I was just gonna go here real quick is what happens, is when we wanna implement logic like this, we end up with something called prop drilling.

For example, if we have that state in a very high component like the app component and the listings all the way down the component tree need to know that. We have to like pass it as like props theme. This is called prop drilling. You've probably seen this before where you just like pass a component props and that component has a child component, you have to pass props there, which has a child component, all that stuff.

Now this can be super difficult to work with and it's bad for like readability. You just don't really know where stuff goes, where it comes from, all that stuff. Now the contextAPI in React uses bit or is a bit different. So instead we can wrap the components that actually need the data in something called a Provider.

And these components if they need to have that data or that stateful data, they can opt in to use that Context. If they don't, that's fine. Because another thing that we saw with Prop drilling is every time the state changes, I'm just going to scroll up a bit in app, all the components re-render, even the components that don't care about the data.

This is of course, something that we want to avoid. But sometimes it's pretty hard to avoid that, especially when many components care about the data like further down the tree, but tha like stateful logic comes from higher up. Yeah, so with the Provider Pattern, we can wrap the components that care about it or at least the parent most components that has all the children to care about it in a Provider.

And this Provider provides a React context which is essentially a component like a stateful components that other components within the Provider can opt in to consume that data. So we have like a provider and we have consumers. For example, here we have the ThemeContext. This is just the kinda based on the example that we saw earlier.

So for example, now we have like state lights by default, but we also have like a theme and then set it. Now the landing page can be wrapped in the Provider because the components within the landing page care about this data. Some refer to them, maybe not TopNav directly, maybe not main directly, but somewhere down there.

They care about this data. Now in this case TopNav does care about it. It's a Consumer. So here we are against the render prop. So it gets the theme component that we passed here as a value from the Provider. So that is essentially like that Context. So they can consume this Context and based on the state changes that we make in the Provider, we can either have a background color of light or dark.

And then we can also have a toggle that uses the setTheme state update. So, even though we see that Main itself doesn't care about, like we don't have any bugs with Main but maybe the toggle is within Main. But we don't have to care, we don't have to worry about the re-render of Main if the Theme Provider update it, because it doesn't directly consume it.

Only the companies that consume it directly will update on a state update. Yeah, this is kind of where the Hooks come in because it's really nice to combine this with React Hooks. So for example, if we have a ThemeContext which is just like stateful objects and we have the Provider here which I like to just create a direct like component.

For it you don't have to do that, you can also just wrap it directly in like this Provider here. But I just like to export it as Provider. So it's like the same everywhere. And then we can also create a custom Hook that's called like useTheme Context, cuz one of the built in Hooks within React is the useContext hook.

And this is the way that other components can opt in to consume the values of the Provider. But this just makes it a bit more clear like, okay, this is just a useTheme Context hook. So now for example, the TopNav cares about the theme. So instead of using like this component, and then there's render prop, which is fine, but it's, I don't know, it's not too pretty.

We can also just use this Hook, like use the Hook. So anytime that theme updates, it actually also just gets it the same way that we saw before. Same with Toggle, because it also exposes that setTheme toggle. Yeah, so this is a really nice way to use Hooks, but this time in like a stateful context.

So we're actually using it to change state or to consume state. Yeah, so one thing just to keep in mind is that, if your component doesn't necessarily care about what the Provider context or I guess here what the Context provides. Just make sure that you don't accidentally end up using it because that will cause a re-render.

But yeah, so only the components that actually should consume it, which is pretty nice. Yeah, and of course it's better for like scalability because we don't run into that render props issue where it's hard to know where certain props come from, it's just nicer. It's way more readable in my opinion, yeah.

We can see that here, so we have another challenge. So the application below contains a listings component and an input components. So what we have here is we have this input components and we're again using that useListings Hook that we saw before, in order to render the listings here, I know it's really bad CSS but to render the listings here.

However, we're also using this components in the listings. So what ends up happening and I'm just going to open this in a new tab, is that we're unnecessarily fetching the listings twice, which you can I guess see. Let me just reload this. I don't know what container hard reload is the way to go, right here.

Yeah, so you can see that it fetched it twice cuz we're calling useListings twice both in the inputs and in the listings components. So instead, what I would like you to do is to create a Provider that wraps both the input and the listings and that consumes this or that uses this useListings Hook.

But it makes sure that it just fetches it once because it can pass it down or it can provide it to these consumers input and the listings. So we don't accidentally fetch it twice for no reason

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now