React's Context API Guide with Example
In this blog, You will learn What React's Context API is and how to use React's Context API. It is very much used as a state management tool, oftentimes replacing Redux.
According to the React doc:
Context provides a way to pass data through the component tree without having to pass props down manually at every level.
To be more clear, this provides a way for you to make values available to all components of your application, no matter how complicated your application is.
When to use context
1const App = () => {
2 return(
3 <ParentClass color= "blue"/>
4 );
5}
6const ParentClass = (props) => (
7<ChildClass color= {props.color} />
8)
9const ChildClass = (props) => (
10<GrandChildClass color= {props.color} />
11)
12const GrandChildClass = (props) => (
13<p>Color: {props.color}</p>
14)In the above code, we designed the application in which used color props in the ParentClass and passed that props to all component (top to down) without checking that it is required by the child class or not and another issue also here that in case if GrandChildClass component was more deeply nested than it was very difficult to manage. This is the problem that Context solves. Context is designed the share values that can be considered "global" such as preferred language, current user, or theme.
Using context, we can avoid passing props. Let's create the above example code using context:
We will create a separate component for context that we can use throughout the components.
Once you have initialized your project, create a file called ColorContext.js in your /src folder.
Create Context
Using React.createContext, we can create context and pass anything as an argument to React.createContext. In our case, we are passing "white" color to provide a light theme.
This will also give me ColorContext.Provider and ColorContext.Consumer. What these two components do is straightforward:
- Provider - The component that provides the value
- Consumer - A component that is consuming the value
1import React from "react";1const ColorContext = React.createContext("white");
2export default ColorContext;To use this context all over the components, we have to use the provider. According to React document, every context object comes with a Provider React component that allows consuming components to subscribe to context changes.
Providing Context
After successfully creating context, we can import context and use it to create our provider.
As we want to access context in the entire application, we need to wrap our app in ColorContext.Provider.
1import ColorContext from './ColorContext';
2 function App() {
3 const color= "white";
4 return (
5 <ColorContext.Provider value = {color}>
6 <div className="App">
7 <header className="App-header">
8 <img src={logo} className="App-logo" alt="logo" />
9 <h1 className="App-title">Welcome to my web page</h1>
10 </header>
11 </div>
12 </ColorContext.Provider>
13 );
14 }Consuming the context
The approach to providing context is the same for class and functional components but consuming is a little different for both.
class component
Mainly used way to accessing context in class component using static contextType. After that, you can access the context value using this.context. You can refer to it in any lifecycle method and even in the render method.
1import ColorContext from './ColorContext'
2class Page extends Component {
3static contextType = ColorContext;
4componentDidMount() {
5const colorValue= this.context
6console.log(colorValue) // "white"
7
8}
9render() {
10return <div>Color Value is {colorValue} </div>
11}
12}The traditional way to accessing context values is by wrapping the child component in Consumer. From there, You can access values as props.
1import { ColorContext} from './ColorContext'
2class Page extends Component {
3render() {
4return (
5<ColorContext.Consumer>
6{(props) => {
7return <div>{props}</div>
8}}
9</ColorContext.Consumer>
10)
11}
12}Functional component and Hooks
You can use useContextin functional components and its equivalent of static contextType.
1import React, { useContext } from 'react'
2import ColorContextfrom './ColorContext'
3export const HomePage = () => {
4const colorValue= useContext(ColorContext)
5return <div>{ColorContext}</div>
6}Updating Context
We can update the context by updating the normal state. We just need to create a wrapper class that contains the state of context and the method to update it.
Example code with file ColorContext.js
1import React, { Component } from 'react'
2const ColorContext = React.createContext()
3class ColorContextProvider extends Component {
4// Context state
5state = {
6color:""
7}
8// Method to update state
9setColor = (color) => {
10this.setState((prevState) => ({ color}))
11}
12render() {
13const { children } = this.props
14const { color } = this.state
15return (
16 <ColorContext.Provider
17 value={{
18 color,
19 this.setColor,
20 }}
21 >
22 {children}
23 </ColorContext.Provider>
24)
25
26}
27}
28export default ColorContext
29export { ColorContextProvider }Now you can update and view the user from the Context method.
1import ColorContext from './ColorContext'
2class Page extends Component {
3static contextType = ColorContext;
4render() {
5const { color, setColor } = this.context
6return (
7 <div>
8 <button
9 onClick={() => {
10 const newColorValue= "black";
11
12 setColor (newColorValue)
13 }}
14 >
15 Update Color
16 </button>
17 <p>{`Current Color Value: ${color}`}</p>
18 </div>
19)
20
21}
22}In my opinion, It is much easier to use than Redux and requires very little code, so why wouldn't you use it?
The problem with the context is simple: ** Everything that consumes the context re-renders each time the state of that reference changes. **
This means that if you're consuming your context everywhere in your app, or worse, using one context for the state of your entire app, you'll end up re-rendering a ton everywhere.

