Have you heard of the context API in React? If you've heard of it, are you like many others afraid to use it directly because you saw this in the official docs:

The first result of that search is showing "Why Not To Use Context". Doesn't inspire a whole lot of confidence in the context API. To make things even more concerning, that section says:

If you want your application to be stable, don’t use context. It is an experimental API and it is likely to break in future releases of React.

So why use context?

Have you ever experienced the pain of trying to get state from the top of your react tree to the bottom? This pain you're feeling is called "prop drilling" and it's super annoying. You wind up having to pass props through components that don't care about the data just so you can send it down to components that do care. And as you move components around this pain is magnified.

You could actually use a regular JavaScript module to avoid these problems. Just put the data in a singleton module and poof, it's accessible/importable anywhere. But then you have trouble with updates (you have to implement an event emitter to notify subscribers when there are updates), and server side rendering can be problematic with singletons as well.

So this is where state management libraries like redux comes into play. They allow you to get data from the store easily anywhere in the tree. All you have to do is use this thing called a <Provider /> and magically your store data is accessible by any component that is "connected."

What if I told you that the <Provider /> is using this experimental context feature 😱 Indeed it is! The provider component puts the data into context, and the connect Higher Order Component pulls the data out of context. So in reality, redux isn't allowing your data to be accessible anywhere... context is!

So, why should you use context? Well, you probably already are and loving it! Even if you're not using context directly, your app is making use of it via react-redux , MobX-react , react-router , glamorous , and more!

Context Reborn

So we love context , but remember that warning that "it is likely to break in future releases of React"? IT'S COMING! And you're going to love it!

Over a month ago, the React team created a new RFCs repository inspired by Yarn's, Rust's, and Ember's. The first pull request to that repository is from Andrew Clark (react core team member) and it's called "New version of context". In it, Andrew outlines what the new version of context will be. There's interesting discussion in there. A few days later, Andrew opened a PR to React called "New context API".

So what does it look like? Whelp, it's about a million times more intuitive than the old context API. Here's the simplest example I can come up with:

const ThemeContext = React.createContext('light') class ThemeProvider extends React.Component { state = {theme: 'light'} render() { return ThemeContext.provide(this.state.theme, this.props.children) } } const ThemeConsumer = ({children}) => ThemeContext.consume(children) class App extends React.Component { render() { <ThemeProvider> <ThemeConsumer>{val => <div>{val}</div>}</ThemeConsumer> </ThemeProvider> } }

You might notice in my example I'm using a render prop (the best!), but actually there's nothing about the context API that requires you to use a render prop. You could easily implement a Higher Order Component or something else using the context API.

The new context API consists of three main parts:

React.createContext which is passed the initial value (and optionally a fancy opt-out function that uses a bitmask). This returns an object with a "provider" and a "consumer"

which is passed the initial value (and optionally a fancy opt-out function that uses a bitmask). This returns an object with a "provider" and a "consumer" The provide function is used higher in the tree and accepts the value (which can be anything).

function is used higher in the tree and accepts the value (which can be anything). The consume function is used anywhere below the provider in the tree and is passed a function which returns JSX (this resembles a render prop component, except the consume function is not a component).

I'm extremely excited about this API. The React team will remove the warning about context being an experimental feature because it's now a "first-class feature" of the framework. This means that people will hopefully be less concerned about using it to help solve the prop-drilling problem in their apps which hopefully will help people not feel like they have to reach for redux so early to solve that pain and they can instead stick with vanilla React for longer.

I recently tweeted:

People's fixation with keeping render methods small aggravates the "prop drilling problem" which makes folks want redux to help alleviate it

So I think if we avoid prematurely and arbitrarily breaking up render methods, we'll feel this pain even less. But even when we do feel it, we'll have a solid, core React API to lean on to help us avoid the problem.

Practical Context

One question that I've seen a lot about the new context API (or the render prop pattern in general) is how to compose providers and consumers together. When you put a bunch of render prop components together in a single render method, things can get... nested:

So what can we do to avoid this? Well, to be perfectly honest I don't think it's all that bad personally. But if it does bother you, then you can solve it the same way you solve the problem in regular JavaScript: utility functions/components. Here's an example:

const ThemeContext = React.createContext('light') class ThemeProvider extends React.Component {/* code */} const ThemeConsumer = ({children}) => ThemeContext.consume(children) const LanguageContext = React.createContext('en') class LanguageProvider extends React.Component {/* code */} const LanguageConsumer = ({children}) => LanguageContext.consume(children) function AppProviders({children}) { return ( <LanguageProvider> <ThemeProvider> {children} </ThemeProvider> </LanguageProvider> ) } function ThemeAndLanguageConsumer({children}) { return ( <LanguageConsumer> {language => ( <ThemeConsumer> {theme => children({language, theme})} </ThemeConsumer> )} </LanguageConsumer> ) } class App extends React.Component { render() { <AppProviders> <ThemeAndLanguageConsumer> {({theme, language}) => <div>{theme} and {language}</div>} </ThemeAndLanguageConsumer> </AppProviders> } }

The goal here is to take common use cases and make special functions/components to make those use cases more ergonomic. Just like you do in regular JavaScript! Makes sense right? I hope it does anyway 😅

Conclusion

Like I said, I'm super stoked about this API. It's currently unreleased, but will be included in the next minor React release. Don't worry, the old context API will continue to work until the next major release, so everyone should have time to migrate. And don't forget that the React team has over 50,000 react components at Facebook they need to consider when making changes like this. There will quite probably be a codemod released to automatically update most everyone's code (as there often is).

I'm excited about what this new API has to offer. As I noted on twitter recently (in response to Dan's tweet):

That's one thing that excites me about the API improvement (in addition to other changes coming). So many new patterns will emerge out of this stuff. Ways of doing things we haven't considered before!!

So much to look forward to! Good luck! 👍

Things to not miss:

Some tweets from this last week:

[POLL]: What do you prefer the render prop be called? A) render <Downshift render={() => {}} /> B) children <Downshift>{() => {}}</Downshift> - 23 Jan 2018 (render won by a little bit)

This is what I'm talking about when I say we should use snapshots effectively (https://blog.kentcdodds.com/effective-snapshot-testing-e0d1a2c28eca): I don't want to hard code the error message and manually update it if it changes, so I snapshot that to make updates easier. But don't snapshot the whole response object! - 24 Jan 2018 (there are screenshots)

I was interviewed on @fixateoncode on my approaches for becoming a better dev: http://fixate.it/podcast/consume-build-and-teach-kent-c-dodds/ - 25 Jan 2018

This week's blog post is "Concerning toolkits 🛠 📦". It's the published version of my newsletter from two weeks ago. If you thought it was good, go ahead and give it some claps (👏x50) and a retweet:

P.S. If you like this, make sure to subscribe, follow me on twitter, buy me lunch, and share this with your friends 😀