In short, the reason this is happening is because deletingTeams gets its value before your asynchronous call. The reasons why are subtle!
What's going on is, when you use detetingTeams in the then function for deleteTeam, the callback function you pass in is using a JavaScript feature called function closures. The variable deletingTeams is used in your then function - but it's not defined by that function! So it can't have local function scope. Where exactly is it coming from, then?
The answer is nuanced. The variable is defined in your first line: const [deletingTeams, setDeletingTeams] = useState([]);. At this point, the variable is assigned a value based on your components' current state - the teams you currently have before deleting. Then, you reference it in your function. At this time, the variable deletingTeams becomes added to the then functions' scope. It is a reference to the same variable outside the function!
Ok, so the reason that deletingTeams is an empty array is because it's an empty array when you create the then function, right? Not quite. Any changes to deletingTeams are reflected when you execute the then function. But in your example, deletingTeams never changes its value. Your component's state changes when you call setDeletingTeams, but you only look up the state once - at the beginning of the block of code. There's no magic that will change deletingTeams' value; for that, you have to call useState again.
deletingTeams is given a fresh value each time your component rerenders. But unfortunately, the then function's closure scope is only determined once. (Each time you rerender, you actually generate a new then function, scoped to that render's version of the deletingTeams variable!) The component may have rerendered, but the then block is still called with the same stale value.
So, altogether, here's what's going on:
deletingTeams is assigned a value in your first line: const [deletingTeams, setDeletingTeams] = useState([]);
- You update the state with
setDeletingTeams, but useState is only called once, so deletingTeams is never updates to match new values.
deletingTeams gets a new value on each new render of your component, but by then, your then function is unfortunately already bound to a specific, past deletingTeams variable that never updates.
- So when your
then block executes, deletingTeams has a stale value.
So what is the correct approach, then? We can read the state in the then function to get the freshest value of deletingTeams. It's simply this.state.deletingTeams. Here's more information: https://reactjs.org/docs/hooks-state.html#reading-state
(Because you're using arrow functions, the then function automatically uses the same this as the component, so everything should work.)
So this should do the trick:
const [deletingTeams, setDeletingTeams] = useState([]);
const handleDelete = (teamId) => {
setDeletingTeams([...deletingTeams, teamId]);
deleteTeam(teamId).then(() => {
let newState = this.state.deletingTeams.filter((id) => id !== teamId);
setDeletingTeams(newState);
});
};
(Be sure to use this.state.deletingTeams instead of calling useState again in this kind of situation. Calling useState inside of nested functions or callbacks can lead to bugs: https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level)