Course Content
React Mastery
React Mastery
Using Context in a Real-World Scenario
Let's create a blog source about the planets. We will use Context
to avoid prop drilling. The app will consist of the following components: App
, Filter
, PlanetList
, and PlanetItem
. To visualize their hierarchy, please refer to the image below.
Step 1
Create the Context
in the context.js
file at the top level.
import { createContext } from "react";
const Context = createContext();
export default Context;
Step 2
Let the entire app know that we are using context. So, we need to wrap the whole app with the Context.Provider
in the App.jsx
file.
import React from "react";
import Context from "../context";
import Filter from "../Filter/Filter";
import PlanetList from "../PlanetList/PlanetList";
const App = () => {
return (
<Context.Provider>
<div>
<Filter />
<PlanetList />
</div>
</Context.Provider>
);
};
export default App;
Step 3
At this step, we must set the context's data (value
prop for the Context.Provider
component). Let's begin by rendering some data. Data is presented in the form of the array of objects:
const planetData = [
{
id: "3a6d44da-bbe2-4ac2-a622-7ca5f321b71c",
name: "Mercury",
weight: "3.3011 Γ 10^23 kg",
size: "4,879 km",
distanceFromSun: "57.9 million km",
material: "Rocky",
image:
"https://codefinity-content-media.s3.eu-west-1.amazonaws.com/code-1/react/react-hooks-%26-context/mercury.png",
existenceYears: "4.5 billion years",
},
...
{...}
];
Here's what we'll do:
Import data from the data.js
file
import data from "../data";
Initialize the state for the planets
as an empty array using the useState
hook.
import React, { useState } from "react";
// ...
const [planets, setPlanets] = useState([]);
Use the useEffect
hook to assign the imported data to the planets
variable. This ensures that we have data to render.
import React, { useState, useEffect } from "react";
// ...
useEffect(() => {
setPlanets(data);
}, []);
Create the variable appData
, representing the entire app data, which will be an object with the planets
state.
const appData = { planets };
Assign the appData
variable to the value
prop of the context provider.
return (
<Context.Provider value={appData}>
<div>
<Filter />
<PlanetList />
</div>
</Context.Provider>
);
Full code of the App.jsx
file after the step three.
import React, { useEffect, useState } from "react";
import Context from "../context";
import data from "../data";
import Filter from "../Filter/Filter";
import PlanetList from "../PlanetList/PlanetList";
const App = () => {
const [planets, setPlanets] = useState([]);
useEffect(() => {
setPlanets(data);
}, []);
const appData = { planets };
return (
<Context.Provider value={appData}>
<div>
<Filter />
<PlanetList />
</div>
</Context.Provider>
);
};
export default App;
Step 4
Let's take a look at the PlanetList
component. Its purpose is to render a specific markup. Inside this markup, we utilize the PlanetItem
component. It's worth noting that we don't pass any props or utilize context within this component since there is no need to work with data at this level.
import React from "react";
import PlanetItem from "../PlanetItem/PlanetItem";
const PlanetList = () => {
return (
<ul>
<PlanetItem />
</ul>
);
};
export default PlanetList;
Step 5
In this step, we need to access the data in order to render the information about the planets. To do this, we will follow these steps:
Import the Context
from the context.js
file.
import Context from "../context";
Use the useContext
hook to retrieve the planets
data from the context.
import React, { useContext } from "react";
// ...
const { planets } = useContext(Context);
Render the markup using the map
function, which allows us to iterate over the data set in React. Apply destructuring to access all the properties of each planet object.
return (
<>
{planets.map(
({
id,
name,
weight,
size,
distanceFromSun,
material,
image,
existenceYears,
}) => (
<li key={id}>
<img src={image} alt={name} width={160} />
<div>
<h3>{name}</h3>
<p>
Weight: <span>{weight}</span>
</p>
<p>
Size: <span>{size}</span>
</p>
<p>
Distance form Sun: <span>{distanceFromSun}</span>
</p>
<p>
Material: <span>{material}</span>
</p>
<p>
Old: <span>{existenceYears}</span>
</p>
</div>
</li>
)
)}
</>
);
Full code of the PlanetItem.jsx
file after the step five.
import React, { useContext } from "react";
import Context from "../context";
const PlanetItem = () => {
const { planets } = useContext(Context);
return (
<>
{planets.map(
({
id,
name,
weight,
size,
distanceFromSun,
material,
image,
existenceYears,
}) => (
<li key={id}>
<img src={image} alt={name} width={160} />
<div>
<h3>{name}</h3>
<p>
Weight: <span>{weight}</span>
</p>
<p>
Size: <span>{size}</span>
</p>
<p>
Distance form Sun: <span>{distanceFromSun}</span>
</p>
<p>
Material: <span>{material}</span>
</p>
<p>
Old: <span>{existenceYears}</span>
</p>
</div>
</li>
)
)}
</>
);
};
export default PlanetItem;
Full app code:
Please take a moment to review the entire project, paying attention to the overall functionality and structure. For now, it is suggested to focus on understanding how the data is passed and rendered in the different components. Note how the data is obtained and utilized in the child components, excluding the Filter
component. The Filter
component will be a challenge in the next chapter, so you can further enhance the app's functionality.
Thanks for your feedback!