Context In React

Table Of Contents

Introduction

React offers the ability to build out web applications quickly. One of the details of this strategy includes passing data to different components in the DOM. This can consist of needed data to build features, states of a component, and anything you can think of.

Data In React

One great pattern in React is how data can be passed through the different components. However, this can get messy.

An application might be broken down like below.

Basic layout of an app

A collection of components. Some of these components return other components. These are called parent components, and their children are nested components.

We can pass data back and forth throughout the lifetime of each component. Working with only props, for example, lets us pass data down the tree to the components that need it. However, this can present a problem.

Using props or properties is a great way to handle data. However, the deeper the component is buried, the more you have to pass the props down. This is called prop drilling.

React app with only Props

Using the workflow above, we have a couple of nested components passing the Username prop down the tree. The Page and MainContent props are just passing down the props used by the UserCard component like a vertical game of telephone.

Now combine this with having to scale out your context to include hundreds of bits of data or state, which need to be passed down to various components at various levels of the tree, and we’ve got a problem.

Context in React

Context solves the problem by allowing us to pass down data without relying on continually passing props through components. Context in React should be used handling global data that does not have to change often. Using context to keep track of our username state improves the workflow by allowing components to use context as needed without passing it down the tree. Pictured below.

React with Context

As illustrated above, we can provide the context to one component, and the children component will be able to access the context regardless of the level they are at. All without needing to have their parent components pass the data down.

Context In Use

So let’s look at an example of context. I created a small React app and just made some barebones components. The first file we should check out is the App component.

App.js file

There are some lines of note, as you’ve undoubtedly seen, and then some other stuff needed for using context. The first out-of-place thing is using the React function React.createContext(), which we use to create a context object. We also made a provider for our context object and wrapped our Page component in it.

Context works using Providers and Consumers. In this case, we are looking to provide the context to our app for consumption by the components. So we use the provider tag, which every context object has, to pass in the value string to our nested components.

The value attribute is a prop that the provider accepts and can pass down the tree. Many consumers can subscribe to one provider, and we’ll talk about that more.

We’re not passing anything to the Page component except the Header and MainContent components.

Page.js component

Let’s look at the Header component.

Header.js component

The header is a regular old React component. However, we use the React hook React.createContent() to subscribe to the UserContext object that we import into this component from the App component. We can now use the curly brackets to pass in the userNameContext into the JSX being returned by the component.

Let’s look at another example. Below we have our MainContent component.

MainContent.js component

Just another component with a nested component, UserBox. Let’s look at what is in the UserBox component.

userbox.js.png

The UserBox component can do as our header did; import the context object, subscribe to the provider using the useContext hook and pass in the context using that context object. This is cool because we’re using context two levels below from where it was created without passing props through subsequent components.

The app would look something similar to the below image. We can see the username string in the header and the UserCard components. I am not one for styling things effectively, so hold your judgments.

The Whole App

Conclusion

Changing the value of the state would cause a render for the other components subscribed to the context. So it could cause issues if the state is constantly changing. So context fits nicely with a global state that is not likely to change often.

The code for the above example can be found on my GitHub.

This has been an interesting learning experience. I’m happy to have gotten one of the fundamentals of React down on paper, so to speak. I hope this helps someone new coming into the React scene.

-George