DEV Community

Hassam Ali
Hassam Ali

Posted on • Originally published at hassamali.com

React encapsulating data fetching logic with container components

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>
   )
 );
};
Enter fullscreen mode Exit fullscreen mode

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 });
         }
       })}
   </>
 );
};
Enter fullscreen mode Exit fullscreen mode

This is how we can use the StarShipInfoLoader and StarShipInfo together.

 <StarShipInfoLoader id={id}>
   <StarShipInfo />
 </StarShipInfoLoader>
Enter fullscreen mode Exit fullscreen mode

Top comments (0)