React encapsulating data fetching logic with container components
Hassam Ali
Posted on December 5, 2021
Container components are components that encapsulate the data loading and data management for the child application.
Let’s say you have a component called StarShipInfo
component which lists the information about starship
const StarShipInfo = (id) => {
const [starShip, setStarShip] = useState(null);
useEffect(() => {
const fetchStarShip = async () => {
const response = await fetch(`https://swapi.dev/api/starships/${id}/`);
const data = await response.json();
setStarShip(data);
};
fetchStarShip();
}, [id]);
return (
starShip && (
<div>
<p>Name: {starShip.name}</p>
<p>Hyper Drive Rating: {starShip.hyperdrive_rating}</p>
<p>Manufacturer: {starShip.manufacturer}</p>
<p>Class: {starShip.starship_class}</p>
</div>
)
);
};
By using container component pattern we can separate out the data fetching logic into a separate container.
First, let’s create a separate component called StarShipInfoLoader
. The purpose of this component is to create a fetch request, wait for the request to be completed, and then render the StarShipInfo
component. The StarShipInfo
component is passed as a children prop to this component, we access the passed component and render it with data.
const StarShipInfoLoader = ({ id, children }) => {
const [starShip, setStarShip] = useState(null);
useEffect(() => {
const fetchStarShip = async () => {
const response = await fetch(`https://swapi.dev/api/starships/${id}/`);
const data = await response.json();
setStarShip(data);
};
fetchStarShip();
}, [id]);
return (
<>
{starShip &&
Children.map(children, (child) => {
if (isValidElement(child)) {
return cloneElement(child, { starShip });
}
})}
</>
);
};
This is how we can use the StarShipInfoLoader
and StarShipInfo
together.
<StarShipInfoLoader id={id}>
<StarShipInfo />
</StarShipInfoLoader>
Posted on December 5, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.