Many years ago the Context API was introduced as an experimental feature with a warning “in the future this API can break”. As the Context API was experimental, most React developers were not confident enough to use it.
A few months back, React shipped many amazing things in v16.3 ,like the new Context API, strict mode, async mode and also updated the lifecycle methods. The new Context API is stable, more efficient and production ready. You can now use this with more confidence, and I’ll show you how.
Context API is a way to enable components to share some data without explicitly passing via each component manually.
Context is like a global object to the React component sub-tree.
Nearly every developer knows that React components are structured like a tree. There is one root node where all the components are connected. In this tree structure, the data flows in only one direction — from top to bottom.
Here is a quick representation of the components of a basic music player app. It has the title of the current song playing, artist name, album name, current time and play control buttons.
Here, the root components contain the information of which song is being played and passes the information to the Header component and to the other components like AlbumTime component and PlayButton component via props.
As the data flow is one direction in React. When any data is required at
nth level, the data will have to be passed as a prop through all the child components. Sometimes, this becomes a soul-destroying task for developers. To solve this, many people use state management libraries like Redux and MobX.
If you have ever used any of these libraries, you have already used Context API indirectly 😁. As redux internally uses old experimental context API.
Is it an eye-opening moment for you?
Read this awesome blog about Redux Provider and connect by Soham Kamani
The below is a quick visual representation of how context helps in making the data available to all the components.
We now understand how context solves the problem of prop drilling. Let’s list down some specific use cases where React Context will prove to be a life saviour.
The ability to set the theme is one of the best UX. E.g medium provides dark mode and light mode which makes it easy to read in the low light situation.
To implement themes, it is required to repaint every component with new color and change few images, if we do not use the context, it will be a chaos to repaint every component by passing new theme via props.
- Multilingual application
To implement multiple languages in app we have to change the text in every component and replace with the translated text. This can be easily implemented using Context.
We can set the current language in the React context and all the components in a massive component tree can display text in the selected language. Using this we save prop drilling all the way down to the components.
- Authorisation: setting the user role and info
This is one of the very common use cases. Many apps require to have dynamic content and messages based on the type of user has logged in. We can easily add User info in the Context and any component can pick info from a Context. We would be able to save all the prop drilling manually to all the levels.
Please share in the comment section what are the other use cases, where you are using Context API.
Here is a quick demo of how we can use the context.
Play with the demo app by changing theme and languages.
Please refer the git repo which contains the code of above demo.
One of the most important things about React is that the data flows in only one direction, which enables the developers to predict, easy debugging and write code which does not do any magic.
The one-way data flow happens via
props, hence the props play a vital role. The
props also act as the documentation for the components and make it reusable within the app and even outside the app.
If we heavily use Context just to avoid prop drilling then we are not going in the right direction. We are making it tightly coupled and the reusability of components would be compromised.
In software development, more quality time spent in designing saves many upcoming weeks of effort.
We should not heavily use Context for everything. Take time, think and design properly and if you see a few sets of data have been passed to many levels down the tree and it is going to be very hard to manage, then take a call and use Context.
Context should be used only for the data, which will be used at various levels in the React component tree.
React team has done a great job by keeping Context API very simple to implement. The are two main actors, the
Provider provides the object in context and the
Consumer consumes these data from the context in sub-tree.
Let’s implement the themes so that we know in detail.
- Create a context
The first step is to create a context using the create method. The components at the different level will use the same context to get the data.
createContext returns a pair of Provider and Consumer components and takes on defaultValue of the current context. Refer line 18 in above gist.
React allows us to create multiple contexts in one app. For better maintainability and separation of concern, we should create a separate context which would serve only that purpose. For example, we can have different contexts like
UserContext. These separate files for context increase the maintainability and glorify the separation of concerns.
Provider is a component which enables the Consumers to subscribe to the context changes. Provider accepts a
value prop and the data in this prop is available to all the child consumers.
In many scenarios, this value needs to be dynamic and changes in runtime e.g theme selection changed by the user from UI, then we can store it and pick from the component state.
toggleTheme, refer to the line number 17 in below gist, changes the value in state and the child consumers get the new value.
Below is the example component which Provides the context to Header and Body component.
Consumer is a getter of context. The components can subscribe to context values by wrapping the Consumer around it. Consumer needs a method with a parameter which returns a react node and composes with the app.
value prop passed from Provider of the current context above in the tree and is captured in the
theme variable by the consumer. Refer line 9 in below git gist.
Don’t you think the brand new Context API is just amazing? Implementing themes and multiple languages were never so easy.
I hope this post was helpful to you.
Please feel free to comment below with any questions or suggestions and consider applauding 👏 if you liked this post and most importantly: Keep Reacting and keep learning 😊 Please feel free to comment below and ask me anything!