I have an async method called getInitialData to fetch all necessary data from an API. Once the data is fetched, I am passing the data into a table. But by the time the data has been fetched, the data is already passed into the table without having all the necessary data, specifically the second api call to fetch the userItemName. Is there a way to wait for all the data to be fetched first before displaying it?
Here’s how I fetch data using the API
const getInitialData = async () => {
const username = user.username;
await axios
.get(`http://localhost:8080/api/sellers/${username}/someData`)
.then((response) => {
for (const key in response) {
if (key === "data") {
response[key].forEach(async (item) => {
item.name = await getUserItemName(username, item.id);
});
}
}
setTableData(response.data);
});
};
useEffect(() => {
getInitialData();
}, []);
This is my second API to fetch further data from the database, called in the first API fetch
async function getUserItemName(username, id) {
const response = await axios.get(
`http://localhost:8080/api/sellers/${username}/items/${id}`
);
return response.data.name;
}
Here’s my table component
{tableData && <SortingTable ref={sortingTableRef} columns={TABLE_COLUMNS} data={tableData }/>}
3
Answers
You can use to fetch the data with for await
Here’s how you can achieve your desired result, the issue is you can not use forEach with await
I updated the loop to for loop, instead of forEach.forEach doesn’t wait for each asynchronous operation to finish before moving on to the next iteration. This can result in race conditions or out-of-order execution of asynchronous tasks.
Also, where are you storing the response from
getUserItemName
? as outside the scope and on every loop you’re losing the item.nameyou can use the map and promise all to get the data for all the data received from the first API call.
Try this :