Context, Simply Put
Tags: beginners, react, context, tutorial
Published: 2023-02-20 20:36:55


When I started to learn React, I was overwhelmed by the concept of Context so I immediately forgot everything I read and decided I would just never use it. Then I had to drill state and setState 5+ components deep in a bootcamp project and I thought maybe I should give Context another chance. At that point I was more familiar with state and component trees and armed with that confidence (and a playlist of youTube videos) I set out to understand and implement Context in my app, and lets just say I nailed it. Here is my simplified explanation for anyone just starting out with Context.

**What is Context?**

Context is a way of accessing data through your whole component tree without having to pass props down manually at every level. Once Context is created you can import it in any component you wish to access the data. Simply put, its like creating a global state.

**When to use Context?**

I had read a few suggestions to use Context sparingly which was part of the reason I didn't spend time learning it initially, and frankly, I don't heed that advice now. For me, Context makes my code feel a lot cleaner and better managed.  If I need access to a piece of state in 3 or more components, I'm using Context. That is especially true if I'm going update the state and I want the change to persist across all pages of my app. Common examples people use for Context are setting a dark theme and referencing if a  user logged in. I personally use it often with data I have fetched from an API.

**How to do it:**

We will need to do two things to use Context: 

1. Establish Context with `createContext` and wrapping components that will use the context in a `Context.Provider`.

2. Importing the context in the consumer component with `useContext`. (With a bonus method of importing Context at the end!)

First, decide where you want to store your context data. I like to put it in a separate Context component and import it to my App component. This keeps my code tidy but you can also establish Context directly in your App component. Like state, you just want to make sure it lives in a parent to all the components that will eventually import the data. If you are storing context in a Context component like me, you will need to pass it a `{children}` prop. 

In the Context component import `createContext` from react with your other hooks. In this example, I'm going to `useState` to store the data we will pass as context to the consumer components. 

Next we will need to use the `createContext` hook to declare our context _outside_ our Context component using the `createContext()` function. We declare the context outside the Context component because we are going to export it for use in our consumer components. 

Your code should look like this so far:

![One](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bf2cntgk1156w4wh40bj.png)

Now we need to tell React what data our `DataContext` we just created will hold. This is usually where I would `useEffects` to fetch data from an API and assign it to a state variable but to keep our example clean and simple I'm just going to declare the state with a default value of an array of numbers. 

From here we create the 'provider component' for the `DataContext` as a return from our Context component. This `DataContext.Provider` component takes one prop called `value` which we assign `data` (our state from the previous step) and wraps around the `{children}` prop we gave to our Context component earlier. Like this: 

![Two](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qah5ujvfnw72wpbszixx.png)

What if we wanted to use `setData` in another component of the app? Well, we could declare another context and call it something like `UpdateDataContext` and wrap both our child and `DataContext.Provider` in the `UpdateDataContext.Provider`. If this were unrelated data, I would probably go ahead and do that.

Instead since `setData` is part of our data state, in our `DataContext.Provider` we set our value to an array of `[data, setData]`. This will pass both our `data` and `setData` function to our children components in our single `DataContext.Provider`.

![Three](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h0c05amidx6qqonwfscl.png)

The final step in our provider component process is to import our Context component to our App component and wrap it around all the children, or 'consumer components' we want to pass our data to. 

![Four](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ghe781itp06hs6a96zlt.png)

At this stage, our `data` and `setData` are available to all the components in our app without having to pass any props! Amazing, but how do we access them? Thats step 2...

useContext

Lets go directly to ComponentC, bypassing components A and B. Here we will import `useContext` from react as well as our `DataContext` from our Context component.

![Five](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vkfc5ixui2gc3m675tvp.png)

We'll then take the `useContext` hook, pass it `DataContext` and declare the variables we will be setting the data to in ComponentC. 

![Six](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vo7vgehi0emi5nczgeja.png)

Viola! You now have access to your `data` state and `setData` function in  ComponenetC to use as you wish with out having to pass the prop through multiple components. 

TLDR: 

To recap, in order to create globally accessible state with Context in your app we:

Created the Context Provider by:

1. Creating a Context component and passing it a prop of `{children}`.
2. Importing `createContext` from react
3. Declaring and exporting our `DataContext` from `createContext()` outside the Context component. 
4. Declaring the state we will use as our context data inside the Context component.
5. Wrapping our `{children}` in the `DataContext.Provider` that has one prop of value and setting it to the state we declared in step 4. 
6. Exporting our Context component and importing it in the App component to wrap around all the components in our app. 

Accessed the Context in our consumer component by:

1. Importing `useContext` from react and `DataContext`
 from our Context component in our consumer component. 
2. Assigning our `data` and `setData` variables using `useContext` and passing it our `DataContext`. 

**Bonus!**

The above works just fine but one more thing I like to do to streamline my code is rather than importing `useContext` in my consumer, I export a function that returns `useContext()` from my Context component so I only have to import this function to to access my data in my consumer components. This is what it looks like in both `Context` and `ComponenetC`.

![Seven](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h9nh2v7tez5r65ztrdxn.png)

What we did was:

1. Import `useContext` in the `Context` component and remove it from `ComponentC`.
2. Export the `useData` function that returns `useContext(DataContext)`.
3. Imported `useData` in ComponentC.

Thats it! After setting up Context once or twice I felt a lot more confident but I did reference my notes on future tries so write your own workflow or save this blog for future reference!