React / 3 MIN READ
Fetching Data
Finding and Delivering
From the original Fervor library. Examples may use older package versions.
Fetching data for a card
Here’s an example of a component fetching data and passing data to another component as a prop:
import React, { useState, useEffect } from "react";
function App() {
const [data, setData] = useState([]);
useEffect(() => {
fetch("https://api.example.com/items")
.then(response => response.json())
.then(data => setData(data))
.catch(error => console.error(error));
}, []);
return (
<div className="App">
{data.map(item => (
<Card key={item.id} item={item} />
))}
</div>
);
}
function Card({ item }) {
return (
<div className="Card">
<h2>{item.title}</h2>
<p>{item.description}</p>
</div>
);
}
export default App;
In this example, the Card component is separated and the data for each card is passed to it as a prop (item). Within the Card component, these props are accessed to display the title and description of each card.
This is a common pattern in React and is often used to make code more reusable and easier to manage. You can now reuse the Card component in other parts of your app, and it will correctly display as long as it’s passed an item prop with the correct shape.
Looking at how fetch works
Alright, let’s dive a bit deeper into how the fetch API works with this code.
The fetch function in this code is being used to make an HTTP request to an API at "https://api.example.com/items". When the fetch function is called with this URL, it returns a Promise that resolves to the Response to that request, whether it is successful or not.
fetch("https://api.example.com/items")
Once this promise resolves, the .then() method is called with a function that takes the Response object and calls its .json() method. This is another Promise that resolves with the result of parsing the body text as JSON.
.then(response => response.json())
Once the promise from .json() resolves, another .then() method is called with a function that updates the component’s state with the data.
.then(data => setData(data))
This causes the component to re-render with the new data.
If any of these promises reject (i.e., if there’s an error), the .catch() method at the end catches the error and logs it to the console.
.catch(error => console.error(error));
This fetch is inside a useEffect hook with an empty dependency array ([]), which means the effect will run once when the component mounts and not again after that. This is equivalent to componentDidMount in a class component.
useEffect(() => {
// fetch code here
}, []);
Now when the data has been fetched and the state is updated, the App component re-renders. In the render method, it maps over the data array and for each item, it creates a Card component with a key of item.id and a prop of item. These Card components are what get displayed on the page.
{data.map(item => (
<Card key={item.id} item={item} />
))}
In the Card component, it takes in item as a prop and displays the title and description properties in h2 and p tags respectively.
function Card({ item }) {
return (
<div className="Card">
<h2>{item.title}</h2>
<p>{item.description}</p>
</div>
);
}
So to summarize, when the App component mounts, it fetches data from the server and stores it in its state. When this data changes, it re-renders and passes the data to Card components as props, which then also render this data.