Deep Dive into New React Context API

React 16.3 release introduced a long-awaited rework of the new React context API!
Until now, context API was considered experimental. If you’ve used it before you’ve probably seen the warning message in the console forecasting it’s rebirth.
Context is an advanced and experimental feature. The API is likely to change in future releases.
This is why I adore the React core team, they take backward compatibility seriously and are careful not to introduce an API that might be rendered obsolete in near future.
It’s often a good practice to defer decision-making processes as late as you can; early and rushed decisions will only cause unforeseeable impact leading to an inevitable rework of existing parts.

React team being aware of this, implemented the first context API since it’s a critical feature, but declared it experimental. This way, we were able to use it while the React team deferred the official implementation producing a much more mature and stable API in the future — And the future is now!
So, what’s the Context API?
Essentially it’s just a dependency injection strategy. Context makes it possible to provide data to directly to any component without using props.
- Provider
- Consumer
- React.createContext
These are the only three things you will need to understand to use context.
Provider
A React component that allows Consumers to subscribe to context changes.
Accepts a value
prop to be passed to Consumers that are descendants of this Provider. One Provider can be connected to many Consumers. Providers can be nested to override values deeper within the tree.
Consumer
A React component that subscribes to context changes.
Requires a function as a child. The function receives the current context value and returns a React node. The value
argument passed to the function will be equal to the value
prop of the closest Provider for this context above in the tree. If there is no Provider for this context above, the value
argument will be equal to the defaultValue
that was passed to createContext()
.
Let’s get our feet wet.
React.createContext("Scuba Manager")
creates a new context with default value of “Scuba Manager”. createContext returns an object containing a Provider and Consumer components which we can now use to, you’ve guessed it — provide and consume our newly created context anywhere in the tree!
In the example above, the value
prop was passed to the Provider hence overriding the default value specified upon context creation.
If no value
prop was passed to the Provider, Consumer would fallback to a default value which is “Scuba Manager”.
* Note that passing a value
prop with a value of undefined
doesn’t cause the context to fallback to the default value, instead it is accepted as a value.
Contact

Looking for software development experts?
No more prop drilling
When a deeply nested component needs data that is defined far up in the component hierarchy we must pass that data through props of every intermediate component until we get to the targeted component.

Component tree is bloated with the currency
prop.
App component defines the currency, e.g state = {currency: "USD"}
. Payment component needs currency to render the amount of money.
Since Payment is a rendered deep down in the tree, all of its parent components now must expect currency
prop and pass it down to its children until it propagates to the Payment.
Prop drilling doesn’t only bloat our codebase but also reduces reusability of “drilled” components. PaymentScreen and PaymentList should not know about the currency, their job is to render the view rather than provide dependencies to the children.

Don’t use context just to avoid passing props a few levels down. Stick to cases where the same data needs to be accessed in many components at multiple levels. — React docs
As you can imagine, context is easy to abuse. We should always stick with props until complexity of the tree increases so much that your brain lags when trying to comprehend the entire structure or more likely, just to avoid unnecessary bloat.
We don’t need Redux anymore!
If you just removed Redux from your app you might as well$ yarn add redux react-redux
If you’re only using Redux to avoid passing down props, context could replace Redux — but then you probably didn’t need Redux in the first place.
– Mark Erikson (Redux maintainer)
Context is not to replace Redux. React-redux uses context internally to provide data to connected components on store updates.
Redux is a complete state management solution (store-reducers-actions) while context is just a dependency injection.
We’re waiting for a React-redux release that will implement the new React context API. There’s already a functional branch which implements it.
Follow the steaming hot discussions regarding the new context API regarding async rendering in this pull request and roadmap discussion.
Emerging patterns & pitfalls
Thanks to the simplicity and practicality of the new React context API, there are new evolving ideas and patterns emerging in the ecosystem.
Unstated is a new minimalist state management alternative to Redux.
No actions, no reducers, just setState
— Sounds perfect for small apps where Redux brings more overhead than management.https://medium.com/media/e83b3297f13e57337b5ca57a1387598e
Composing multiple consumers
Since the new API adopted render props pattern it also inherited its imperfection when it comes to nesting multiple render props. Code readability decreases significantly with each additional render prop.
With the use of React-composer, we can avoid this code drift by composing consumershttps://medium.com/media/a69988196ff2b5a275a2bcb9276be020
Context shadowing
I haven’t seen a use case anywhere yet, but according to the docs nested Providers override parent Provider’s context which is analogous to variable shadowing.
I feel like there might be some interesting patterns emerging from this possibility but I’m really stretching my imagination right now. If you’ve seen any patterns which rely on this feature please let me know.