DEV Community

Timo Prüße
Timo Prüße

Posted on • Originally published at Medium

React: Stacking Context

Just the other day, I encountered an unusual challenge when working with the React Context API. I’m eager to share what I learned and how I worked around the restrictions that it has.

Photo by [Claudia Wolff](https://unsplash.com/@kaimantha?utm_source=medium&utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral)


Scenario

Take a look at the following simplified code snippet:

The context’s value is dependant on the name prop. That means the values for outer_context and inner_context differ.


Problem

The most inner component ComponentThatUsesContextFromBothProviders needs the values of both context providers it is wrapped in. However, by default, it is only possible for us to get the context of the closest provider, which would be inner_context in this case.

First things that might come to your mind now are:

Pass the value of the outer context as a prop to the inner component

We don’t want to do that because we would end up with prop drilling again in more complex scenarios where we would need to pass it down the whole tree. The React team introduced the Context API to prevent precisely that.

Use some kind of state management

We don’t want to overcomplicate things with state management since our use case is straightforward, and we don’t want to pollute our global state. Only the components wrapped inside of the context providers need to know their values.


Solution

Finding a leverage point

The value of our context is dependant on the name prop we set for the provider. That means the context that is computed for each name should be different. We know that we might need all of the individual key/value pairs when a component is wrapped inside of multiple providers.


How does that help us?

Oversimplified our structure needs to look like this to provide that functionality:

outer_context -> Component A -> inner_context -> Component B

Component A Context = { outer_context: 'outer_value' }

Component B Context = {
  outer_context: 'outer_value',
  inner_context: 'inner_value'
}

Maybe you did already see where I’m heading with this. As the title of this article suggests, it makes sense to stack our context in that case. If we now introduce a new component C, it needs to have all the context of the component B plus the new context that is provided.


How can we achieve a stacking context?

It’s just a few lines of code as seen in the following snippet:

There’s no magic involved. Instead of saving the context’s value directly, we create an object that is indexed by the name prop in this example. Every context provider now only needs to use the existing context and ‘push’ it’s own value to the stack. Now we can get the values like this:

You can also create a custom hook to make it more convenient to get the value and handle the case of a non-existent key.


Conclusion

Sometimes it makes sense to ‘bend’ the React world a bit and break out of the boundaries set by it. Do what fits best to the scope of your project. Just remember that everything is just JavaScript in the end. ;)

Top comments (0)