I have an api endpoint such as this and I need to make a put request to this endpoint.
api/user-group/{id}/invite/{userId}
The problem i'm having is my form contains a multi-list, react select list that allows users to select as many groups as they want and so everytime a user selects a group I'm storing the groups id in local state but my api endpoint only takes in one group id. The solution I think is too loop over the group ids and do separate requests. Can someone guide me on how to achieve this solution or is there a better solution?
My Code:
const AddUserToGroupPage = () => {
const [currentUserId, setCurrentUserId] = useState('');
const [GroupIds, setGroupIds] = useState([]);
const { inviteUserToGroup } = useUserGroupApi();
const InviteExistingUser = async () => {
const body = {};
const res = await inviteUserToGroup({
id: groupIds,
body,
userId: currentUserId,
});
return res;
};
const onGroupsSelected = (selected) => {
if (selected) {
setGroupIds(selected.map((select) => select.value));
}
};
return (
<>
<Select
name="userGroups"
label="User Groups"
placeholder="Select as many groups as you want"
id="userGroups"
defaultOptions
options={groups}
isMulti
onSelectChange={onGroupsSelected}
/>
</>
)
}
I think you can achieve what you want like this:
const InviteExistingUser = async () => {
const body = {};
return await Promise.all(
groupIds.map((groupID) => {
return inviteUserToGroup({
body,
id: groupID,
userId: currentUserId,
});
}),
);
};
In this code, the call to groupIds.map() will return a list of Promises that each resolve to the return value from a call to inviteUserToGroup (one result for each group ID).
Then you can pass that list to Promise.all, which returns a Promise that resolves to a list of results. So basically you go from Promise<result>[] (a list of promises) to Promise<result[]> (a promise for a list).
Then you can await that Promise, at which point you end up with a list of results for all the calls to inviteUserToGroup.
You have 3 options:
GroupIds.forEach(g => {
const body = {};
const res = await inviteUserToGroup({
id: g.id,
body,
userId: currentUserId,
});
// save response
setGroupsInfo(prev => [...prev, res]
})
const requests = GroupIds.map(g => {
return inviteUserToGroup({
id: g.id,
body,
userId: currentUserId,
});
})
Promise.all(requests).then(resArray => {
setGroupsInfo(resArray)
})
// take 5 each time
for(let i = 0; i < GroupIds.length; i += 5){
const subGroupsIds = GroupIds.slice(i, i + 5);
// fire 5 requests
const requests = subGroupsIds.map(g => {
return inviteUserToGroup({
id: g.id,
body,
userId: currentUserId,
});
})
// wait for the 5 requests
const resArr = await Promise.all(requests);
setGroupsInfo(prev => [...prev, ...resArr]);
}
the second option is the worst, since you could have so many groups and you can't request all of them in the same time.
the 3th option is the optimal one but it's implementation is not straight forward.
the first option is easy and but on large number of groups will be slow.