React Context and Hooks: An excellent way to pass data
Tags: react, javascript, webdev
Published: 2022-01-26 09:59:28


## 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4zltfqix0mihrgwleiun.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ejlksir2kz2afok635n7.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jb2khw6sq1ey7dubvsu2.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c5telth3u4sl37o6x7co.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d8m1hlqfnk7lumtnnpw3.png)

Running this app, you would get the following result:

{% codesandbox vh0nd %}

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
- [How to use React Context effectively](https://kentcdodds.com/blog/how-to-use-react-context-effectively) by [Kent C. Dodds](https://twitter.com/kentcdodds)
- [React Context official docs](https://reactjs.org/docs/context.html)