Understanding Context API In React.js
September 9th, 2022 | By Jay Raj | 9 min read
Understanding the context API in React.js is vital to sharing data across components in React.js. It allows the React app to create global variables that can be passed around.
Data is one of the essences of any application. For a web app to be functional, it requires 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, used for passing or sharing data across components in React.js. It provides a way to pass data across the component tree.
What is Context API?
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 with five components.
Data from the parent component is only required at the fifth component. In that case, you'll be required to pass data from each component to another as props until it reaches the last one.
This process is tedious and requires props to be passed at each level, even though they're not mandatory 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 the Context API?
Using the context API reduces the tedious process of passing the required data as props to each level. Although it makes reusing components difficult, it does the job.
Seeing Context API in Demo
Now let's see Context API in action.
We'll start by creating a React app and making it functional by passing data as props. And we'll see how and where to use the 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 localhost:3000.
For the sake of this tutorial demo, we'll require a couple of components. So, let's create them to have a component tree.
Creating Different Levels of Components
By default, inside the src folder, we have the App.js file. Here, it is the default component rendered inside the index.js file.
We'll be using Bootstrap to design our React app. So, let's install React Bootstrap on our app using npm.
npm install react-bootstrap bootstrap
Once React Bootstrap is installed, you can import the components. You are ready to 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 use the Dashboard to use the Accordion bootstrap component.
Dashboard component
Inside the src folder, create a folder called components. Inside components, create a folder called a dashboard. Then, 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 to see the accordion inside the React app.
Tab Component
Inside the accordion, we'll show the data in tabular 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. This one will be nested inside each of the tabs.
List Component
Inside src/components/list, create a file called list.js. Import the ListGroup component and execute 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 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 you click the accordion, you’ll see a set of tabs. Inside those, a list of items is shown.
Let's see how you can pass some data from the dashboard to the List.
Sharing Data Using Props
On clicking the accordion, imagine the first item you want to show in the list group component is the clicked accordion name. To do that, you need to pass that data as a prop to its child components.
We have three components: the dashboard, tabs, and lists.
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 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;
The tab component has no use for accordion data except passing 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 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 the 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);
By clicking on 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);
}
By clicking on 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 you 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 clicking on each accordion, its name will show as the first entry in the respective list group.
Final Thoughts
In this tutorial, you learned what the 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.
The source code for this in-depth tutorial can be found on GitHub.
Jscrambler
The leader in client-side Web security. With Jscrambler, JavaScript applications become self-defensive and capable of detecting and blocking client-side attacks like Magecart.
View All ArticlesMust read next
React.js: Communication between Components with Contexts
In this blog post we present a small but illustrative example on how to use React.js contexts in Components communication.
March 25, 2015 | By José Magalhães | 3 min read
Facts You Should Know About React
In spite of its popularity, React has many well-kept secrets newcomers might not know and seasoned veterans may not have yet realized.
June 20, 2018 | By Camilo Reyes | 4 min read