September 9, 2022

Understanding Context API In React.js

By Jay Raj | 9 min read

0509_Blogpost_1024x512_V1

Data is one of the essences of any application. For a web app to be functional it requires the data to flow from one part of the application to another. From a React or Angular application's perspective, for an app to be up and running data needs to be passed from one component to another.

In this tutorial, you'll learn about the Context API which is used for passing or sharing data across components in React.js. It provides a way to pass data across the component tree. This is extremely useful when we have several components down the component tree.

What is Context API

From the official documentation,

Context provides a way to pass data through the component tree without having to pass props down manually at every level.

Let's break it down with the help of an example. Imagine a component tree structure having 5 components. Data from the parent component is only required at the 5th component. In that case, you'll be required to pass data from each component to another as props until it reaches the last component.

This whole process is quite tedious and requires props to be passed at each level even though it's not required at those levels. Using the Context API you can share data among a tree of components without passing it as props at each level.

Why Use It?

Using Context API reduces the tedious process of passing the required data as props to each level. Although it makes reusing components a bit difficult, still it does the job.

Seeing it in Demo

Now let's see Context API in action. We'll start by creating a React app and make it functional by passing data as props. And then we'll see how and where to use Context API for sharing the data.

Creating React App

We'll be making use of create-react-app to create our React project. So, first, you need to install create-react-app using npm.

npm install -g create-react-app

Once done you can use it to create your react app.

npx create-react-app react-context-app

The above command creates a boilerplate code for you to get started.
You can navigate to the react-context-app folder and start the react app using npm start.

You will have the default boilerplate react application running at http://localhost:3000/.

For the sake of this tutorial demo, we'll require a couple of components. So, let's create components to create a component tree.

Creating Different Level components

By default inside the src folder, we have the App.js file. Here App is the default component that is being rendered inside the index.js file.

We'll be making use of Bootstrap to design our React app. So, let's install React Bootstrap to our app using npm.

npm install react-bootstrap bootstrap

Once React bootstrap is installed you can import the required components and use them in your React components.

Add the following bootstrap css import in index.js to install bootstrap globally inside the app.

import 'bootstrap/dist/css/bootstrap.min.css';

Let's start by creating an Accordion in our React app. First, we'll create a component called Dashboard which will be using the Accordion bootstrap component.

Dashboard component

Inside the src folder create a folder called components. Inside components create a folder called dashboard and inside it create a file called dashboard.js. Import the accordion in dashboard.js and use it as shown:

import Accordion from 'react-bootstrap/Accordion';

const Dashboard = () => {
  return (
    <Accordion defaultActiveKey="0">
      <Accordion.Item eventKey="0">
        <Accordion.Header>Accordion Item #1</Accordion.Header>
        <Accordion.Body>
          Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
          eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
          minim veniam, quis nostrud exercitation ullamco laboris nisi ut
          aliquip ex ea commodo consequat. Duis aute irure dolor in
          reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
          pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
          culpa qui officia deserunt mollit anim id est laborum.
        </Accordion.Body>
      </Accordion.Item>
      <Accordion.Item eventKey="1">
        <Accordion.Header>Accordion Item #2</Accordion.Header>
        <Accordion.Body>
          Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
          eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
          minim veniam, quis nostrud exercitation ullamco laboris nisi ut
          aliquip ex ea commodo consequat. Duis aute irure dolor in
          reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
          pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
          culpa qui officia deserunt mollit anim id est laborum.
        </Accordion.Body>
      </Accordion.Item>
    </Accordion>
  );
}

export default Dashboard;

Save the changes and reload the app and you will be able to see the accordion inside the react app.

Tab Component

Inside the accordion, we'll show the data in a tab format. So, let's create a tab component. Create a folder called tab inside src/components and create a file called tab.js. Here is how it looks:

import Tab from 'react-bootstrap/Tab';
import Tabs from 'react-bootstrap/Tabs';

const MyTab = () => {
  return (
    <Tabs
      defaultActiveKey="employee"
      id="uncontrolled-tab-example"
      className="mb-3"
    >
      <Tab eventKey="employee" title="Employee">
        
      </Tab>
      <Tab eventKey="profile" title="Profile">
        
      </Tab>
    </Tabs>
  );
}

export default MyTab;

Include the Tab component inside the accordion body.

import Accordion from 'react-bootstrap/Accordion';
import MyTab from '../tab/tab';

const Dashboard = () => {
  return (
    <Accordion defaultActiveKey="0">
      <Accordion.Item eventKey="0">
        <Accordion.Header>Accordion Item #1</Accordion.Header>
        <Accordion.Body>
            <MyTab />
        </Accordion.Body>
      </Accordion.Item>
      <Accordion.Item eventKey="1">
        <Accordion.Header>Accordion Item #2</Accordion.Header>
        <Accordion.Body>
            <MyTab />
        </Accordion.Body>
      </Accordion.Item>
    </Accordion>
  );
}

export default Dashboard;

Now let's create one more component called List which will be nested inside each of the Tab.

List Component

Inside the src/components/list create a file called list.js. Import the ListGroup component and create the List component. Here is how it looks:

import ListGroup from 'react-bootstrap/ListGroup';

const List = () => {
  return (
    <ListGroup>
      <ListGroup.Item>Cras justo odio</ListGroup.Item>
      <ListGroup.Item>Dapibus ac facilisis in</ListGroup.Item>
      <ListGroup.Item>Morbi leo risus</ListGroup.Item>
      <ListGroup.Item>Porta ac consectetur ac</ListGroup.Item>
      <ListGroup.Item>Vestibulum at eros</ListGroup.Item>
    </ListGroup>
  );
}

export default List;

Include the List component inside the Tab component. Here is how the tab.js looks:

import Tab from 'react-bootstrap/Tab';
import Tabs from 'react-bootstrap/Tabs';
import List from '../list/list';

const MyTab = () => {
  return (
    <Tabs
      defaultActiveKey="employee"
      id="uncontrolled-tab-example"
      className="mb-3"
    >
      <Tab eventKey="employee" title="Employee">
        <List />
      </Tab>
      <Tab eventKey="profile" title="Profile">
        <List />
      </Tab>
    </Tabs>
  );
}

export default MyTab;

Save the above changes and reload the app. You will be able to see a couple of accordions and when clicking the accordion, you’ll see a set of tabs. Inside the tabs, a list of items is shown.

Let's see how you can pass some data from Dashboard to List

Sharing Data Using Props

Now on clicking the accordion, let's say the first item you want to show in the list group component is the clicked accordion name. In order to do that you need to pass that data as props to its child components.

We have three components, Dashboard, Tab, and List. Let's first pass the accordion name as accordionData props from the Dashboard to the Tab component.

Inside the Dashboard component you can pass the data as shown :

<MyTab  accordionData="Item #1"  />

You can access this data inside the Tab component using props as shown and pass it to the List component. Here is how the Tab component looks:

import Tab from 'react-bootstrap/Tab';
import Tabs from 'react-bootstrap/Tabs';
import List from '../list/list';

const MyTab = (props) => {
  return (
    <Tabs
      defaultActiveKey="employee"
      id="uncontrolled-tab-example"
      className="mb-3"
    >
      <Tab eventKey="employee" title="Employee">
        <List accordionData={props.accordionData} />
      </Tab>
      <Tab eventKey="profile" title="Profile">
        <List accordionData={props.accordionData} />
      </Tab>
    </Tabs>
  );
}

export default MyTab;

Tab component has no use of accordionData except to pass it along to the List component.

Similarly, you can access the props inside the List component and render the name of the accordion as the first item in the list. Here is how the list.js file looks:

import ListGroup from 'react-bootstrap/ListGroup';

const List = (props) => {
  return (
    <ListGroup>
      <ListGroup.Item>{props.accordionData}</ListGroup.Item>
      <ListGroup.Item>Dapibus ac facilisis in</ListGroup.Item>
      <ListGroup.Item>Morbi leo risus</ListGroup.Item>
      <ListGroup.Item>Porta ac consectetur ac</ListGroup.Item>
      <ListGroup.Item>Vestibulum at eros</ListGroup.Item>
    </ListGroup>
  );
}

export default List;

Save the above changes and reload the app. On clicking the accordion you'll be able to see the name of the accordion as the first item in the list.

For showing the accordion data we are passing the name of the accordion from the Dashboard component to the Tab component and from Tab to List, even though there is no use of accordionData inside the Tab component.

Let's see how Context API reduces the effort of passing data from each component level in a component tree.

Using Context API for Data sharing

We'll create a context from the Dashboard component. In order to do so you need to use React.createContext in the Dashboard component as shown:

const  default_accordion_name = "Item #1";
export  const  AccordionContext = React.createContext(default_accordion_name);

On click of the accordion, the name will change, so we need a state variable to keep track of it. Let's define it as shown:

const [accordionData, setAccordionData] = useState(default_accordion_name); 

const handleOnClick = (name) => {
    setAccordionData(name);
} 

On click of the accordion, we also need to add the onClick handler.

onClick={() =>  handleOnClick('Item #1')}

To use the AccordionContext you need to contain the Dashboard component inside the AccordionContext as shown:

<AccordionContext.Provider value={{ value: accordionData }}>
      <Accordion defaultActiveKey="0">
        <Accordion.Item eventKey="0" onClick={() => handleOnClick('Item #1')}>
          <Accordion.Header>Accordion Item #1</Accordion.Header>
          <Accordion.Body>
            <MyTab accordionData="Item #1" />
          </Accordion.Body>
        </Accordion.Item>
        <Accordion.Item eventKey="1" onClick={ () => handleOnClick('Item #2')}>
          <Accordion.Header>Accordion Item #2</Accordion.Header>
          <Accordion.Body>
            <MyTab accordionData="Item #2" />
          </Accordion.Body>
        </Accordion.Item>
      </Accordion>
</AccordionContext.Provider >

Here is the complete dashboard.js file:

import { useState } from 'react';
import Accordion from 'react-bootstrap/Accordion';
import MyTab from '../tab/tab';
import React from 'react';

const default_accordion_name = "Item #1";
export const AccordionContext = React.createContext(default_accordion_name);

export const Dashboard = () => {

  const [accordionData, setAccordionData] = useState(default_accordion_name); 

  const handleOnClick = (name) => {
    setAccordionData(name);
  } 

  return (
    <AccordionContext.Provider value={{ value: accordionData }}>
      <Accordion defaultActiveKey="0">
        <Accordion.Item eventKey="0" onClick={() => handleOnClick('Item #1')}>
          <Accordion.Header>Accordion Item #1</Accordion.Header>
          <Accordion.Body>
            <MyTab accordionData="Item #1" />
          </Accordion.Body>
        </Accordion.Item>
        <Accordion.Item eventKey="1" onClick={ () => handleOnClick('Item #2')}>
          <Accordion.Header>Accordion Item #2</Accordion.Header>
          <Accordion.Body>
            <MyTab accordionData="Item #2" />
          </Accordion.Body>
        </Accordion.Item>
      </Accordion>
    </AccordionContext.Provider >

  );
}

As you might have noticed in the code above, we are passing the value to the AccordionContext as:

<AccordionContext.Provider value={{ value: accordionData }}>

Now, this value can be accessed anywhere inside the component tree under the Dashboard component. So don't need to pass unnecessary data to every component level.

To access the data passed in Context, you need to make use of the useContext hook.

const  accordionData = useContext(AccordionContext);

where AccordionContext is imported from the Dashboard component. Here is the modified list.js file which shows how to access data from Context.

import ListGroup from 'react-bootstrap/ListGroup';
import {AccordionContext} from '../dashboard/dashboard'
import { useContext } from 'react';


const List = (props) => {
  const accordionData = useContext(AccordionContext);

  return (
    <ListGroup>
      <ListGroup.Item>{accordionData.value}</ListGroup.Item>
      <ListGroup.Item>Dapibus ac facilisis in</ListGroup.Item>
      <ListGroup.Item>Morbi leo risus</ListGroup.Item>
      <ListGroup.Item>Porta ac consectetur ac</ListGroup.Item>
      <ListGroup.Item>Vestibulum at eros</ListGroup.Item>
    </ListGroup>
  );
}

export default List;

Save the above changes and reload the app. On click of each accordion, its name will show as first entry in the respective list group.

Final Thoughts

In this tutorial, you learned what Context API is and what its use is. You saw how it reduces the effort of passing props down to each component level even though it's not required in those components.

Hope you liked this tutorial. Source code from this tutorial can be found at GitHub.

Author
Jay RajSoftware Developer @CodeHandbook. A seasoned developer with keen interest in creating stuff for the web using JavaScript and related frameworks.
View All Posts

Subscribe to our weekly newsletter

Learn more about new security threats and technologies.

I agree to receive these emails and accept the Privacy Policy.
Projeto Co-Financiado por (Mais info)