I’m running into an issue with setState where it is being called again while it is currently finishing up the previous setState batch.
I have an object that is structured like this
[{ id: 0, loading: false }]
Now, on the page I have a toggle button for different id’s and I want each toggle to show a loading overlay when it is being called. When I press the toggle button I am calling a function (shorted down for simplicity) that does the following:
const updateRequestAccess = (requestId, checked, user) => {
updateUserAccessLoadingState(requestId, true); // Set loading to current id
someApi.put(requestId, user, checked).then((response) => {
if (response && !response.error) {
updateUserAccessLoadingState(requestId, false); // Set loading to false
} else {
updateUserAccessLoadingState(requestId, false); // Set loading to false
}
});
};
The function called before and after the Api call is:
const updateUserAccessLoadingState = (id, loading) => {
if (
isUpdatingUserAccess.filter((el) => el.requestTypeId === id).length > 0
) {
const newState = [...isUpdatingUserAccess];
const indx = newState.findIndex((el) => el.requestTypeId === id);
const selected = newState[indx];
selected.loading = loading;
setIsUpdatingUserAccess(newState);
} else {
setIsUpdatingUserAccess([
...isUpdatingUserAccess,
{ requestTypeId: id, loading },
]);
}
};
What this does it that it makes sure that there is never the same id
twice in the state array and the loading boolean is only changed.
The problem currently is that I noticed when I try to toggle multiple buttons at once, which calls the updateRequestAccess
many times, is that the first state modification does not finish running before the next one starts running right away. This results in some strange behaviour in the state.
How could this be done differently in order to circumvent this issue where the first set state is not finished before the next one starts running?
2
Answers
Try to use
setIsUpdatingUserAccess(oldState => [... oldState, { requestTypeId: id, loading }])
Not exactly, They both run, they both complete and they run in the correct order, but the second call does not make its changes based on the previous state (the one that was produced by the previous call) and so it basically overwrites the first call.
And that’s why you should use an update function when you want to make changes based on the previous state.