Using Context in React

I had the opportunity to speak at React Conf 2018 about the new ways to use context in React. This blog post is a text version of my talk.

Check out the video of it on YouTube:

I’ve recently been helping out a startup called fl33t. It’s an over the air update service. For example, if you have a hardware device and need to update the software on it, you can use fl33t to deploy those software updates.

This is what the main dashboard looks like when you log in to fl33t.com. The fl33t application allows you to group your devices however you want — these groups are called fleets. For example, If you have a fleet of QA devices that need a specific software build, you can deploy the software to that fleet.

To create a new fleet, you click the “New Fleet” button which takes you to a multi-step form with four steps. Each step in this form is a different React component, and all of these components share a single parent component. Since I want to share data across this multi-step form, this is a good use case for using context.

The component hierarchy for the fl33t form

It should be noted though that the context API isn’t meant to be used for every part of your application- it’s meant to be used for sharing data in a tree of React components. From the React documentation:

Context is designed to share data that can be considered “global” for a tree of React components

Before refactoring the code to use context, this is what the instances of the form components in the parent component (the FleetForm.js file) looked like:

Render function in FleetForm.js

You’ll notice a lot of data and functions are getting passed down via props. By using context, we will eliminate the need to pass data or functions down as props and just render the component.

To start out using the context API we create a file, and in that file, we call React.createContext() and save the result in a variable.

Create a FleetContext object

Next, in our parent component, we import the context object from that file.

Import context object

In the case of this multi-step form, I want to share the state of the parent component and two functions that allow me to pass data back up to the parent component when the user interacts with a particular step in the form.

You might have noticed at the bottom of the state object that I’ve added two functions and wondering why those are there. In the render function of our parent component, we’ll wrap our components with a Provider component. The Provider component has a value prop — this is where we add any data we want to share with our child components.

There are some gotchas in using context — if I just added the two methods to an object like the above code for the value prop, it might unintentionally trigger a re-render in the child components because a new object will get created every time the Provider gets re-rendered.

Instead, we put the two methods in the state object and set the Provider value to this.state

It’s a little bit funky, but it works.

For our child components to have access to the data we need to modify them slightly. As of right now, there are three different options for using context in an application.

Option 1

With the release of version 16.3 of React earlier this year, the way to use context in connection with the Providercomponent is to wrap your component in a Consumer component.

This is a valid way to use context, but there are a couple of more ergonomic ways of using context that were released this week, so let’s focus on these newer ways to use context.

Option 2

In version 16.6 of React that was released on Tuesday, the class property contextType was added to allow for a more straightforward way to use context. In the child component first, we import the context object.

Import context object

Then, at the bottom of our class definition file, before we export it, we add the contextType property and set it to the context object we imported at the top of our file.

By doing this we can now access data using this.context For example, in one of the methods in one of the child components, we call this.props.updateFormData

Now we refactor it to call this.context.updateFormData

Option 3

With the new announcement about hooks at React Conf, we now have a 3rd option for how to use context in our application. Since using hooks would require a significant refactor of the steps in my form — I’ll show you what I would do if I wanted to add another step to my form and instantly have access to all the form data and functions without having to pass props down.

First, we’ll import the useContexthook

Next, we import the FleetContext object

Then, in our FleetFormStep5 function, we’ll call the useContext hook which will give us access to the data from the parent component

Finally, we can use the context data and return our component

That’s all there is to it!

If you’re interested in learning more about React — you can purchase Fullstack React: The Complete Guide to ReactJS and Friends

And if you want to get weekly updates on all things React & React Native, sign up for my weekly newsletter — The Fullstack React Newsletter

Happy Coding!

-Sophia