Category Archives: Context API

React Context API: Multiple Consumer and Providers

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 📄

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 📄

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.

React Context API: Three Way Light Switch

In the Way Too Simple Context API example, we made a simple light switch. This post will show why flux, the single source of truth, and Context API are really useful.

The last post had just two components (not counting the App component): a light switch and light bulb. Here we are going to add a second light switch making this circuit mimic the three-way switch common in many homes.

In this system we want the following to happen:

  • flipping any switch will change the state of the light
  • the “physical” direction of the switch shouldn’t matter

This is meant to represent a switch in real life, and physical switches don’t throw themselves in response to a change in the system. On a web app, you’d most likely want the component’s feedback to change to reflect the state of the app. If you are curious about how three-way switches work in electrical circuits, it’s quite interesting. Unlike the electric circuit, our mini React app has a single source of truth and by manipulating that we can affect the whole system.

Luckily, because of the way we designed the original Context API light switch app, adding another switch is easy enough as putting a second light switch in the App.js file in the three-way-switch branch of the Context API example project.

app.js 📄

We also added a few aesthetic things: the three-way class to remove the “on” / “off” label and another spacer, but to make this work, all that was added was just another LightSwitch component!

The magic is in the flipSwitch: () => this.setState({on: !this.state.on }) function in the Provider that gets passed to the LightSwitch component and run when someone clicks on the component. The flipSwitch function also looks at the App component’s state for the on property, negates it, and then sets it as the negated value creating a toggling effect.

Once again, since this is a simple example, we could accomplish this by lifting up the state and sending it back down with props, but with Context API it doesn’t need that direct chain. LightSwitch can place it in other components (like a Room, LightPlate, etc.) as long as they are children of the Provider.

A Way Too Simple React Context API Example

React’s Context API is convenient built-in state management for React Projects. It has it’s advantages and disadvantages over a library like Redux for sending props and changing the app’s state. I’m going to focus on the advantages of using Context API and getting an overly simple example to work.

The example in this post only has two levels of components, so it is actually advised against by the React documents. If you were actually making an app with this few of components it would be easier just to pass props and lift up state. But let’s figure out how Context API works! Below is a mini React Context API app that is a light bulb and a light switch.

I’m going to assume a few things:

  • a working knowledge of React.
  • familiarity with the single source of truth behind the Flux model in React
  • familiarity with ES6 JavaScript syntax

Also, the full code for the project is at https://github.com/seandolinar/context-api-example, but the code excerpts in the post are only the relevant parts (I left out the import statements, etc.). I made it with create-react-app, which is a pretty good quick start boilerplate for playing around with React without a lot of setup time.

Alright! There are really just three normal React components:

  1. the App
  2. the LightBulb
  3. the LightSwitch

The app’s global state only has the lightbulb on/off, which affects only the display of the LightBulb. And that state can be changed by only the LightSwitch. Overly simple; let’s go through some code!

context.jsx 📄

Alright, this is too simple. We create a context that can be imported into the different the components.

app.js 📄

This object is the heart of the app, so let’s start here. We create a state in the App’s constructor, initially setting the state.on = false. The new part is the LightCircuit.Provider Context API component. It wraps the what would have been the root app component. The value attribute of the Provider is the default/starting value. There are two items in the default context:

  • the App’s state [state]
  • a function for changing the App’s state [flipSwitch()]

This will be passed to any Consumer components like in the LightBulb component.

LightBulb.jsx 📄

This component is just a Context Consumer component, and a div that uses the context’s state. The ({state}) => part of the arrow function destructs the context and only uses the state, which is then used to change the className which controls CSS to show the light bulb is lit or dark. The div that’s inside the consumer component could be any component, composition of components, or even JavaScript.

The annoying thing about Context API is having to pass the context through the arrow function. It creates some JavaScript structure I’m not crazy about since it limits what you can do with the context in that component without additional code.

LightSwitch.jsx 📄

The LightSwitch component does one important thing: it runs flipSwitch() from the context, which in turn changes the state in the top-level App component. We are destructuring the flipSwitch() from the context then putting that into a catch all handelClick() function to run when the button is clicked.

I did add one extra layer on complication, I create an up and down state internal to the switch. Since the circuit doesn’t affect the position of the physical switch in real life, so it shouldn’t here. That is why the extra handleClick() function was made and why the LightSwitch component has its own state.

Conclusion

Hopefully, walking through the simple example with Provider, Consumer and Context can help you get Context API working for your app. Again, this is too simple of a demo, and actually a bad example of how to use it. It works well if the light switch was buried within a hypothetical LightPlate, Wall, Room, and Circuit component. That way you wouldn’t have to lift up state through several layers of components.