My React app retrieves a list of Items from a database and stores them in state, like this:
Client.getListOfItems(url) .then((itemList) => { // itemList is an array of Items setItemList(itemList); // Declared as [itemList, setItemList] = useState([]); });
Now I want to modify each Item
in itemList
by adding in some sub-data. Each Item has the key ‘userID’; I want to loop over each item to get the corresponding userID, and then copy that into the Item object. Then the saved itemList should contain a list of Items, each of which has the property ‘user’.
So far I have:
Client.getListOfItems() .then((itemList) => { // itemList is an array of Items const newItemList = itemList.forEach((item) => { Client.getUser(item.userID) .then((user) => { let newItem = {...item, users: user}; return newItem; }) }) setItemList(newItemList); });
but newItemList
is undefined at the point when I’m trying to call setItemList
. How do I achieve what I need here?
Advertisement
Answer
You need to map your list into array of promises, and then use Promise.all
to wait for all promises to resolve, and then use one more then
to set the state:
Client.getListOfItems() .then((itemList) => { const newItemListPromises = itemList.map((item) => { return Client.getUser(item.userID).then((user) => { let newItem = { ...item, users: user }; return newItem; }); }); return Promise.all(newItemsListPromises); }) .then((list) => setItemList(list));
Use with caution, since if at least one promise will fail, Promise.all
will also fail. Don’t forget to catch
your errors