With React’s Context API you are able to use multiple Providers
and Consumers
using different context instances. This could be useful if you want to separate different data models into distinct parts of your app. For example, you could have a data context and a table context. One context instance could be used to control what data your REST API is sending back, while another instance controls your sorting, paging, etc.
Continuing the extremely simple light bulb example, I’ve decided to build multiple rooms (a living room and a hallway) with some switch wall plates and a light in each room. This should be a familiar setup to anyone who has a three-way switch in their hallway, so you can turn the hallway light off at either end of it. In order to make this, we will create:
- “Circuits” (context instances) for the living room and the hallway
- Wall plate components for each room to house light switch components
- A three-way switch for the hallway light
- A normal switch for the living room light
- Light bulbs for each room
Putting that together we get the mini-app below:
The full code is available on my GitHub, but let’s start with the core App
component:
app.js 📄
class App extends Component { constructor(props){ super(props) this.state = {on1: false, on2: false} } //Room (living room) and Hallway are the two different rooms. render() { return (); } }this.setState({on1: !this.state.on1 }) } }> this.setState({on2: !this.state.on2 }) } }> living room hallway
There is a lot of component composition here. We have a WallPlate
component for each room along with a component for the room itself which houses the light bulb. We have the two providers wrapping the both rooms with the values defined in terms of the App’s state and a method that can set that state. For this example we are using numbered circuits:
Circuits (Context instances)
- LightCircuit1 — (Living) Room
- LightCircuit2 — Hallway
The context instances also correspond to a specific variable in the main app components’s state; once again either 1 or 2. In the interest of being straight forward, each context instance have the different states hardcoded into the Provider’s value. If you were using them to control data and the table view separately the Provider’s initial value object should look demonstrably different from each other, but since this is a just a demonstration, they look similar.
The component of most interest is the WallPlateLivingRoom
component. It’s the only component which has multiple consumers. [The rest of the components resemble the last few React Context API examples.]
WallPlateLivingRoom.jsx 📄
class WallPlateLivingRoom extends Component { constructor(props){ super(props) this.state = {up: false} } render() { return} }{ ({flipSwitch}) => } { ({flipSwitch}) => }
I think the Consumer
use is pretty straight forward. You need to first use the correct consumer for what you want to do, then pass the context to your child components as you would with just one component. The React docs show nested Consumer
components, but they don’t need to be.
This is a simple example, so using Context API like this is overkill, but you can see how you are able to use different context instances within your app. If you have questions about the basics of Context API or are curious about some of the building blocks of code used in this example check out the previous posts on this topic: A Way Too Simple Context API Example, Context API: Three Way Light Switch.