I have a function that changes the status of sub-tasks to true <-> false. On clicking the Main task, its child tasks status should turn true. When I’m running this function in a loop it breaks after the first iteration. How can I change the status of every subtask with status false.
my function is
const changeSubtaskStatus = id => { axios.patch(`/subtaskStatus/${id}`) .then(res=>{ setSubTodos([...subTodos].map(ST=>{ if(ST.id===id){ return{ ...ST, status: !ST.status } }else{ return ST; } })); }).catch(err=>console.log(err.message)) }
And my EventListener is here
const onTaskCheck = id => e =>{ changeTaskStatus(id); const subTasks = subTodos.filter(ST=>ST.taskId===id); subTasks.map(ST=>{ if(ST.status===false){ changeSubtaskStatus(ST.id); } }) }
The changeSubtaskStatus works for the first object of the subTasks array and breaks. Please let me know my mistake here. Thanks in advance
Advertisement
Answer
When you enqueue multiple state updates in a loop like this then you should really use a functional state update so each update uses the previous state and not the state from the render cycle the callback was created in. The issue is a javascript enclosure of the state from the render cycle the callback is invoked in.
const changeSubtaskStatus = (id) => { axios .patch(`/subtaskStatus/${id}`) .then((res) => { setSubTodos((subTodos) => // <-- previous state subTodos.map((ST) => // <-- shallow copy array ST.id === id ? { ...ST, // <-- shallow copy ST object status: !ST.status // <-- update property } : ST ) ); }) .catch((err) => console.log(err.message)); };