Nihar's Dev Corner

React Context and Hooks: An excellent way to pass data


What is Context?

A Context is basically a JavaScript object that can be passed from one parent component to several child components efficiently. Props can pass values to components as well. But, if a value needs to be passed to a child component deep in the component tree, using props means the value also passes through components that do not need it. Or, if a value is required by several components, props can make it difficult.

This is a good use case for Context. Props need to be passed from one component to the other. With Context, the parent component provides the value, and the child components that need it can access it.

Passing values with Context and Hooks

Let's take a common example used for demonstrating Context - themes. Consider the following UI:

Image of app UI with various components highlighted

Here, the one with the red border is the main App.js component. The one with the green border is a component called ThemeButton.js, and the one with a blue border is the ThemeWindow.js component. The App component will have the other two as its child components. Clicking the button in ThemeButton will toggle the theme between light and dark. The result of the theme will be reflected in ThemeWindow.

We need to create a context first, then have the App component provide a value for its child components. The child component(s) will consume this provided value. Let's set this up.

1. Creating a context

A context can be created in a separate file or in the App component itself, but it is generally better to create a separate file for it. Since depending on your app, you may need multiple contexts for different features. It can thus be useful to have separate files.

Create a new file to hold the context and export it:

Creating context theme

In this file, we export two things - an object containing theme values and our context. The createContext() function returns a Context object. It accepts an argument for the initial value similar to the useState hook. In this case, the light themes object is the default value of ThemeContext.

2. Passing values with the Provider component

Since the context has been created, let's add it in App.js.

Passing values with Provider component

Every Context object (created with React.createContext()) has a Provider component. This Provider component should be wrapped around all the child components that will be getting access to ThemeContext. Conversely, there is also a Consumer component. You can also use the useContext hook instead if you're not working with class-based components.

You must be wondering why the light object was used as the default value, but the Provider component has passed the dark object. First of all, the value prop used in the Provider component is something React recognizes so you cannot use a different name for that prop.

Whatever is passed through the value prop is what the child components consume. And if a component attempts to access ThemeContext but does not have a Provider component in the tree above, it will use the default value the Context object has (the light theme).

As a quick example, let's say there was a third component called ThemeFont.js. But this third component was not included within the Provider component -

An example showing the scope of Provider

Since ThemeFont is not wrapped by the Provider component, it will not receive the new value. Although it can still access ThemeContext, it will receive the default value, that is, the value we passed to createContext - the light themes object.

Not wrapping a component that needs access to a Context in a Provider component still gives it access to the Context's default value.

Although you probably wouldn't have a reason to do this, it is still good to know.

3. Consuming context in child components

Let's use React Hooks to consume the provided context value.

Consuming context value

Running this app, you would get the following result:

The ThemeWindow certainly has the dark theme. But, the button to toggle the theme doesn't work. The next article will demonstrate how to update values passed via Context.

Some links to resources