Mastering React's Context: A Guide to Efficient State Propagation
Tags: webdev, react, javascript, beginners
Published: 2023-07-09 08:48:05


Hey There,

Welcome to the third post in this **React Demystified** series.

---

Last week, we looked into the `useEffect` hook and tried to understand why it's called that. And also, some fundamental questions like - What exactly is an effect? 
{% embed https://dev.to/kokaneka/things-that-no-one-ever-told-you-about-useeffect-in-react-5fij %}

---

This week, we dig into the React's `Context` and the `useContext` hook. We will dig into the core of what we mean by **Context** and what is the significance of managing it throughout your React app. Let's do this! 🙌🏾

## Some context about `Context`

![Why do you need context?](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7xjnpg24nnt55xoq46m2.png)


We looked at state in our first article in this series & found out that state is something that the UX was tightly coupled with. It was that data, which if changed, would required the UX displayed to the user change as well. 

**So what is `Context`?**
According to the [official docs](https://react.dev/learn/passing-data-deeply-with-context), `Context` is primarily an alternative to passing props:

![What is context](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yh482lklsqdl8im85dc5.png)

What does that mean?
Well, I understand Context as this - It is that data which **does not change frequently**, is relatively **small in size** and can be **consumed anywhere** in the entire application. 

## An example of Context

Let us say that there is some data that does not change frequently - Like the `theme` associated with a website. If we create the theme at the top, like the App component and then want to use it in a button which was several layers deep, we would have to pass it down all the way. 

![Prop drilling](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7bcobl818heb3qxiogop.png)

This is more commonly known as prop drilling. 

The use of `Context` solves this problem. Because instead of passing the piece of data through all the components where it does not get used, we only need three touchpoints:
- **creation** - Where the `Context` is created
- **updation** - Where the `Context` value can be updated
- **consumption** - Where the `Context` value can be read. 

This sketchnote below summarizes it well:
![3 touchpoints of context](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rfbgiwiw39vvgs6vptct.png)

And that is what makes `Context` special. Because it provides us with an interface to tap into this `context` that is somehow magically available to us throughout the app. 

## Coding it up
With that theoretical understanding, let us now work with `Context` with some code. We will look at it from the perspective of the 3 touchpoints discussed above.

### Context creation
For creating `Context` we use the `createContext` function provided to us by React.

``` jsx
import { createContext } from 'react';

export const themeContext = createContext('light');
```
Notice how the created `Context` is exported out from this component. That is because in order to consume the `Context` in any child component, we would first have to import this exported variable (which we will see next). 

### Context consumption
Now, in order to consume the context value created without passing it down as props, we will need to import the above context variable and call the `useContext` hook that will return us the current value. 

``` jsx
import { useContext } from 'react';
import { ThemeContext } from './App.js';

export default function Button({ children }) {
  const theme = useContext(ThemeContext);
  // ...
}
```
The above code runs and, `theme` gets the value of **light**, which was the default value set on the context. 

But, you might wonder what was the need to do all this?

We can get the same result by just creating a constant named theme and exporting it from the `App.js` component. But that is where the next part comes into the picture. 

### Context modification with `Provider`
Anywhere down the component tree below the context creation, its value can be edited using the `Provider` component. 

So, let us say we had a button to tweak the light and dark theme. If that button was tied to a state variable, the current value of the state variable that the button controls could be provided as the value for the provider:

``` jsx
import { ThemeContext } from './App.js';

export default function Main({ level, children }) {
  const [theme, setTheme] = useState('light');

  const toggleTheme = () => {
    setTheme(theme === 'light' ? 'dark' : 'light')
  }

  return (
    <section className="main">
      <LevelContext.Provider value={theme}>
        {children}
      </LevelContext.Provider>
      <Button /> // This button toggles theme
    </section>
  );
}
```
Once we have this in place, if we try to read the `Context` value anywhere using `useContext` down the component tree inside of `children`, we will get the value that is set by this provider. Which inturn is being set via the button. 

Hope that clears a lot of concepts related to `Context` in React and the `useContext` hook. 

See you in the next one!

Cheers 🙌🏾