Avoid Prop Drilling With useContext
Published: 2023-11-23 22:57:22





Bothering the team with all that noise coming from your prop drill? Let’s pause and take a look at a better solution before you dig yourself a hole you can’t get out of: `useContext`. 

When using React, sharing data across components is a give-in – it’s one of the finer features of React which allows for seamless data efficient management, especially when it comes to dealing with larger applications with multiple layers of components. 

![React graph](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v4d9q2plsalbyqnnd3w0.jpg)

For those unfamiliar to React or those just getting started, this is generally done through the downward passing of data, or “props”, from parent components to their children. 

![Parent to child relationship React](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6inx672jrdrh6x4jir2t.png)

But what happens when you’re dealing with deeply nested components or when multiple components need to get the same data? 

![Russian dolls](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oib81ry6ij2dvd99s12t.jpg)

This is exactly where the infamous “prop drilling” can become deceptively appealing, where one would continuously pass down props component after component until the desired child receives the initial prop -- regardless of how many children the props get passed through.

![Diagram of Prop Drilling](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/54jjjari78hoiwppxkzc.png)

While this bruteforce solution can work, good luck trying to follow that trail back up if something, somewhere goes unexpected in the data transmission between components. The higher the volume of drilled components, the higher the difficulty becomes in maintaining and identifying expected behavior and outcomes throughout the nested levels.

![Made in the Abyss anime scene](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kvqxutzaxt0dhsjqtt3j.jpg)

## So why not use a better solution: useContext?

By allowing better optimized and safe data sharing across multiple components, `useContext` is absolutely a viable option to avoid a predicament where props are being passed down a dangerous shaft of varying decrees.

## What is useContext?

In a nutshell, `useContext` is a React Hook which, as implied in the name, allows you to **read** and **subscribe** to a specific _context_ which you’ve built to encompass your component tree. 

When called, the data will appear in a context object which returns the current context value for that context. 

Yes, I do realize that’s a lot of _context_.


![Buzz Lightyear Context Meme](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ldpqg2m8ze8ud2iwop5c.jpg)


Put it this way – a _context_ is like **a magic cloak** that surrounds your component and any of the children subscribed to that component. 

![cloak example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f8thmeyyugl0hc4p464n.png)


Any component falling beneath this magical cloak has been granted the ability to call the `useContext` hook in order to get the predefined information written from the top at _any level_ of your component tree without having to manually prop pass. 

As a _Harry Potter_ fan, I kind of like to think of `useContext` like the _Accio_ spell -- just like how the _Accio_ spell works in retrieving an item called from anywhere so long as its existence is within the vicinity, the `useContext` hook can only call the information if it's been defined and wrapped around the appropriate components through a top level context.

![Harry Potter Accio example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eq5s1rhl5rbduj92yxbr.gif)


. 

## How to use useContext

Essentially, using `useContext` comes down to three fundamental steps: **Create**, **Provide**, and **Consume**.

## 0. [OPTIONAL] Set up your files:

Okay I lied -- this is an additional step and while this isn't particularly mandatory, it's good practice to structure your contexts in a context folder at the same level as your components directly beneath the `src` folder. For reference, this is what my file structure looks like at a basic level:

![React file structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7zyzzbis9egwf1two3ri.png)


## 1. Create a Context: 

The first step is to _create_ your context which is simply done by using the `createContext` function from React. 

In line with my comparison to the context being a magical cloak, I'm going to call my newly created context `MagicCloakContext`:

![Create-Context code example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gbcjx157ob4wmrrt3fsc.png)


## 2. Provide the Context: 

Now to _provide_ the context, you need to wrap the part of your component tree that should have access to the context in a new `Provider` component. 

`createContext` is a function which returns an object with a `Provider` component so in order to provide the context you created in step 1, append your context with a dot and add the `Provider` key to the context you created in step 1:

**MagicCloakContext.Provider**

And once you identify the component(s) you'd like to apply your context to, wrap, or _provide_, your context around the targeted component(s) with your newly made `Provider` component:

`<MagicCloakContext.Provider>
<ChildComponent />
<MagicCloakConext.Provider />`

The `Provider` will then take a `value` prop which will be the current value of the context, or the desired information you want to retrieve, which you can then access in the component(s) and all of their affiliated children.

As you can see in my example, in my `App` component, I am defining a variable called `data` with a string value of `"Accio data!"` which is being passed into my `Provider` component's `value` prop and is the information which I'll want to retrieve throughout my application:

![Provider context code example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1zzec2n9o6pucppanmos.png)



## 3. Consume the Context

Lastly, to access, or _consume_ the data set up by the context, this is where some paths diverge.

While this may sound confusing, just like the `Provider` component attached to `createContext`, there's also a `Consumer` component which is where step 3 "consume" comes from. But to not overly complicate things and for the purpose of this guide in following modern best practices up to this date, don't worry about the `Consumer` as it was replaced with a more elegant and straightforward approach to consuming the context through the `useContext` hook. If you are curious about the `Consumer` component, please refer to the official React documentation on `createContext` [here](https://react.dev/reference/react/createContext).

Now that we've got that disclaimer out of the way, let's use the `useContext` hook, which consumes the context object created from `createContext` and returns its current value.

In my code below, you can see that inside `ChildComponent1`, we're defining a variable `data` with the `MagicCloakContext` being _consumed_ by the `useContext` hook. I am then passing this `data` variable into a `div` block...

![Consume context code example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2ywudci5sbxq2digr6ur.png)

...and since everything worked out, when we run our application, we now see the words "Child Component 1: Accio data!" on the browser:

![Browser example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0u59fie7rhhtk7b5vjbt.png)

Pretty cool stuff, huh? Let's go over a couple more examples to better visualize some other use cases of `useContext`.

## Multiple children example

Here's an example where I wrap multiple components in my `MagicCloakContext`: `ChildComponent1`, `ChildComponent2`, and `ChildComponent3`. 

Again, since all these components are wrapped in our `MagicCloakContext`, they should be able to use `useContext` in order to access our "Accio Data!" without any issues with prop passing like so:

![Multiple children in App code example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cn7gugvvvvgkercsqjtq.png)


![Child component 2 code example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cj3eb3h1a2qkrcvrp3zx.png)


![Child component 3 code example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aez91s9i0cbonmfcpoyr.png)

![Browser example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/43l0tfkldr8agnt2n15u.png)

## Nested Child example

And if this isn't overkill enough, here's a final example of a situation with a triple nested child component inside `ChildComponent1` where we once before would have considered prop drilling, but now don't have to think about it due to the power of `useContext`:

![Child Component 1 code example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6uxnt33u711uzqtm2gv9.png)


![Nested Child Example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mcpzd3hjztusy9pw7s0i.png)


![Nested Nested Child Example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ztqgfdz6pw8teherchrs.png)


![Nested Nested Nested Child Example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/toi3674g2lnkul5lyf47.png)


![Browser Example for Nested squared example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/55t1ax8v9q1tggm97eye.png)

## When To Use / Practical Use Cases

So of course, the examples above only outline a rudimentary example of how to use and visualize `useContext` through simple string data in contention to prop drilling. 

But if you're curious about other use cases to fully take advantage of `useContext`, it's also really great for managing **user authentication**, **theme switching**, **language localization**, **sharing state between components** and **styling** to name a few. 

Furthermore although there are some cases where Redux or other library solutions may work better for managing your global state on larger scale more complex applications, `useContext` isn't a bad solution when you're looking for a simple and convenient way to share information and/or state with React. 

While all of these cases merit attention and exploration, for the sake of this article and sticking to the basics, if you're interested in learning more about any of the above points, I'd be more than happy to write a separate article in the future to further expand on these points.


## Conclusion
So hopefully this read was able to give you a good visual and better clarity on the basics of `useContext`. At the very least, I hope that after reading this article, if you ever feel tempted to grab that prop drill, you'll be reminded of this article and are able to prevent yourself from a despaired life of endless digging. Thank you for checking out my article and let me know if you have any comments or questions at any time -- happy hacking!