I'm new to react. I have a user list that fetched once when the component mounts. and before the results dispatched to the reducer, it needs to loop inside the userlist and get user fullname/title from another endpoint, then add a new property to userlist object. I cant figure out how to wait for all promises (getUserById() function) to finish before calling a dispatch. I tried the solution here, but failed: How to return many Promises and wait for them all before doing other stuff
code below just to illustrate what I want:
const {
listUsers,
fetchUserData
} = useContext(GlobalContext);
const getUserById = async (userId) => {
return sp.web.siteUsers.getById(userId).get().then(user => user.Title);
}
useEffect(() => {
sp.web.lists.getById("8C271450-D3F9-489C-B4FC-9C7470594466").items.get()
.then(userLists => {
userLists = userLists.map(list => {
if (list.Person_x0020_ResponsibleId) {
getUserById(list.Person_x0020_ResponsibleId).then(username => {
list['Person_Responsible'] = username; // -> fetch user fullname and title
})
} else { // -> if id is null
list['Person_Responsible'] = '-';
}
return list
});
fetchListSuccess(userLists); // -> dispatch result to reducer
});
}, []);
You can accomplish this using Promise.all. First you need an array of promises from your second API calls. Then we'll give this array to Promise.all
, and it will wait until they all resolve.
I've rewritten using async/await
syntax. It works the same as using .then
with the promises, but when you're working with a promise chain that's this complex it's easier to follow with async/await
.
useEffect(async () => {
const userLists = await sp.web.lists.getById('8C271450-D3F9-489C-B4FC-9C7470594466').items.get();
const promises = userLists.map(async (list) => {
if (list.Person_x0020_ResponsibleId) {
const username = await getUserById(list.Person_x0020_ResponsibleId);
list.Person_Responsible = username; // -> fetch user fullname and title
} else { // -> if id is null
list.Person_Responsible = '-';
}
return list;
});
await Promise.all(promises);
fetchListSuccess(userLists); // -> dispatch result to reducer
}, []);
A few notes:
userLists
in the map, because you're just adding a property to existing objects. This will happen without the map.Promise.all
to wait until all those promises resolve.