How to use context API in React

Posted by

The concept of the Context API in React is nothing but a way of sharing data to the child component from the Grand component. It is one of the game-changing concepts in React that solves the props drilling problem. We will learn a lot more about this in the later section of this tutorial.

In this tutorial, we are going to explore what is Context API? and why it is necessary? how to use it? and finally, At the end of this tutorial, you will get the core idea about context API and also see why it is necessary for react.

If you wanna learn more about Higher Order Components in React, check out this tutorial

Things You will learn from this tutorial

We will cover the following topics in this tutorial and the topic’s names are given in the below section:

  • The necessity of the Context API
  • The use of the Context API
  • Conclusion

The necessity of the Context API

The concept of props drilling refers to the term where we need to pass our props in such components whose does not need them. Let’s say, we need to pass props from the parent component to the third number of the child components. But to do so, we need to pass the same props to the first and second components also. Which is unnecessary. This concept is called props drilling.

We have bypassed this while using the Higher Order Component. It also does the same thing if you use render props in your program. But avoiding this is not the actual solution. We need to find out a proper solution to this problem.

From this concept, a new pattern arrived in React which name is Context API. You may understand it from its name. It fixes the props drilling problem and we can directly pass props from the global component to the specific component in our program. Let’s see the syntax of this by using our previous tutorials example in the below section:

const CounterContext = React.createContext()

export default CounterContext

Here, you can see that to use the Context API. We need to create it first. This React.createContext() gives us two components. One is the Provider component and the other one is the Consumer component. We can access them in our program by using the CounterContext.Provider and the CounterContext.consumer

The Provider component will be used in the global component that will provide something and the Consumer component will be used in the child component that will consume from the global component. We will see the hands-on example of this in the next section.

The Use of the Context API

We have already known that the Context API emerged because of solving the props drilling problem. But we haven’t experienced this problem yet. Before, using Context API, let’s create the environment for it. That means at first we will create a props drilling situation and then we will use the usage of this.

Creating props drilling situation

We know that Render props and Higher Order Components help us to avoid code reusability. But they bypass the props drilling situation. Let’s create a props drilling problem by using the render props functionality.

Let’s say, we have a Section component that changes the background color and another component name HoverCounter We want to pass this component to the HoverCounter so that it can change the background color as well as implement the hover functionality. We have also added two more components between Section and HoverCounter component so that we can see the actual problem while using the props drilling pattern. Section --> Content --> Counter --> HoverCounter Let’s try to implement a functionality to the Section component in the below code example:

// Section Component

import Content from './Content'

export default function Section(theme){
    return(
        <div>
            <h1>This is a Section Component</h1>
            <Content theme = {theme} />
        </div>
    )
}

Here, you can see that in the Section component we have written some text in the <h1> tag and also imported a Content component. Inside that component, we have passed the theme as props. Let’s see the Content component in the below section:

// Content Component

import Counter from './Counter'
import HoverCounter from './HoverCounter'

export default function Content(theme){
    return(
        <div>
            <h1>This is a Content Component</h1>
            <Counter>
            {(counter, incrementCount) => (
                    <HoverCounter count={counter} incrementCount={incrementCount} theme={theme}/>
                )}
            </Counter>
        </div>
    )
}

Here, inside the Content component, we have also written some text inside the <h1> tag and also imported the Counter and the HoverCounter component. We have passed our props theme here. Now, we will see the functionality of Hover Counter but before doing so we will show you the implementation of the Counter component. We will not describe the codes here.

// Counter Component

import React from 'react';

class Counter extends React.Component {
    state = {
        count: 0,
    };

    incrementCount = () => {
        this.setState((prevState) => ({ count: prevState.count + 1 }));
    };

    render() {
        const { children } = this.props;
        const { count } = this.state;
        return children(count, this.incrementCount);
    }
}

export default Counter;

Here, we have implemented the functionality of counting. We have discussed it in our previous tutorial. You may visit it to get what’s happening here. Now let’s see the HoverCounter component in the below section:

// HoverCounter Component

import React from 'react';

export default function HoverCounter({ count, incrementCount, theme }) {
  const style = theme === 'green' ? {backgroundColor:'green'} : null
    return (
        <div>
            <h1 style = {style} onMouseOver={incrementCount}>Hovered {count} times</h1>
        </div>
    );
}

Here, you can see in the HoverCounter component that we have styled our actual theme At first we received it as props and then used it. We have also given a condition here and that is if our theme is set as green then it will change the background otherwise it will remain the default. Now, let’s see our global component which is App.js in the below section:

// App Component

import React from 'react';

import ClickCounter from './components/ClickCounter';
import Counter from './components/Counter';
import Section from './components/Section';

export default class App extends React.Component{
  state = {
    theme : 'green'
  }
  render(){
    const {theme} = this.state
      return (
        <div className="app">
            <Counter>
                {(counter, incrementCount) => (
                    <ClickCounter count={counter} incrementCount={incrementCount} />
                )}
            </Counter>
            <Section theme = {theme}/>
        </div>
    );
  }
}

Here, we have implemented the other functionality along with the theme Now, if we run the program we will be able to see that the Hovered background is changed to green That means we can easily implement our desired functionality by following the props drilling pattern.

But what is the problem here? Can you notice? Though we are achieving our desired functionality, there’s something occurring that is not perfect. The answer is we are passing the theme props inside the Section Component and the Content component. But there is no use-case of this props inside these components.

Now, what if we need to pass this component inside the 100 more components or even 1000. It will create unnecessary stuffs in our code and our code base will loose its readability. This simply creates the props drilling problem. To avoid this problem, a new pattern introduced in React named Context API Let’s solve this issue by using the Context API in the next section.

Use Context API

We have already discussed that the Context API in react is nothing but a pattern that simply allows us to pass a props from the parent component to the specific child component. This simply provides a Provider component and the Consumer component. Let’s see the below code example of using it so that we can fix the problem that arise in the previous section.

// Context/themeContext.js

import React from "react";

const themeContext = React.createContext()

export default themeContext

Here, at first, we have created a folder into our src folder and named it context Later on, created a file named themeContext.js In this file, we simply stores the react’s Context API and export this file for further used. Let’s use this to the App component.

We have already known that this component provides two component. One of them is the Provider component that is used in the global or parent component. Here, App is our global component. We will use the provider here to provide the theme props. See the below code example:

import React from 'react';

import ClickCounter from './components/ClickCounter';
import Counter from './components/Counter';
import Section from './components/Section';
import ThemeContext from './context/themeContext';
export default class App extends React.Component{
  state = {
    theme : 'green'
  }
  render(){
    const {theme} = this.state
      return (
        <div className="app">
            <Counter>
                {(counter, incrementCount) => (
                    <ClickCounter count={counter} incrementCount={incrementCount} />
                )}
            </Counter>
            <ThemeContext.Provider value = {{theme}}>
              <Section/>
            </ThemeContext.Provider>
            
        </div>
    );
  }
}

Here, you can see that we have wrapped our Section component with the ThemeContext.Provider that is coming from the React’s Context API. Later on, we have passed theme as the value for it. Now, let’s implement the Consume functionality in our Content component in the below section:

import React from 'react';
import ThemeContext from '../context/themeContext';
import Counter from './Counter';
import HoverCounter from './HoverCounter';

export default function Content() {

    console.log('Content rendered');
    return (
        <div>
            <h1>This is a content</h1>
            <Counter>
                {(counter, incrementCount) => (
                   <ThemeContext.Consumer>
                        {({theme})=>(
                             <HoverCounter
                             count={counter}
                             incrementCount={incrementCount}
                             theme={theme}
                         />
                        )}
                   </ThemeContext.Consumer>
                )}
            </Counter>
        </div>
    );
}

Here, you can see that we have wrapped the HoverCounter component with the ThemeContext.Consumer Here, we have already known that Consumer Component is provided by the React Context API that will consumes something that is provided by the global component. In our case it is theme That’s it. Now if you run the program, you will be able to see that the background color turns into green.

This time we do not pass the props inside those components whom do not need to use it. This is the beauty of the react Context API and this is how you can use it.

Conclusion

In this whole tutorial, we have covered what is react context API, why do we need to use it, what type of problem will arise if we don’t use this and finally, how to use this in our program? We have seen each of these steps hands on by doing code. We have also covered the theoretical concept of the Context API in React.

In React, the Context API is a must learning stuff. You can fix or handle many complex situation with the help of this. It is a pattern that can make your code base clear and more readable.

In this article, we have gain the theoretical concept of this pattern and also use this that is provided by the React. We can also create our own Context API like react and use it in our program. That is advanced level. If you want to know how to create a Context API on your own then you may request for one. Finally, this is all about the Context API in react, you may try to use it on your own program by following this article.

Leave a Reply

Your email address will not be published. Required fields are marked *