1

I am creating a list of tasks (simple todo app) using React Hooks and I'm having some issues while deleting one item. I am rendering that list of tasks from an array in the state. I am getting the id of that item, finding the index inside the array, splicing and then setting the new spliced array as the state again, and while I can see the changes on my console, my ui never gets updated. I tried using the useEffect hook but also didn't work out. Can someone please explain what am I doing wrong? Here's my code on the parent component

  const [ todoList, setTodoList ] = useState(data);

  const handleToggleComplete = (id) => {
    let mapped = todoList.map(task => {
      return task.id === Number(id) ? { ...task, complete: !task.complete } : { ...task};
    });
    setTodoList(mapped);
  }

  const deleteItem = (id) => {
    // gets id of the button triggered
    const index = todoList.map(todo => todo.id).indexOf(Number(id))
    // finds index of that id

    const updatedList = [...todoList];
    // splices array .splice(index, 1)
    updatedList.splice(index, 1)
    
    // sets new array as state
    setTodoList(updatedList)
  }

  return (
    <div className="App">

            <Header />
            <TodoList todoList={todoList} handleToggleComplete={handleToggleComplete} deleteItem={deleteItem}/>

    </div>
  );
}

and here is my child component


    const handleClick = (event) => {
        event.preventDefault()
        handleToggleComplete(event.currentTarget.id)
    }

    const handleDelete = (event) => {
        event.preventDefault()
        deleteItem(event.currentTarget.parentNode.id)
    }


    return (
        <div id={todo.id} onClick={handleClick} className={todo.complete ? "todo strike" : "todo"}>
            {todo.task}
            <button onClick={handleDelete}>Delete</button>
        </div>
    );
 };


  • Hi, look at this answer, this is solution for your question https://stackoverflow.com/a/58556049/17684992 – William Melo Dec 15 '21 at 22:12
  • I think you need to show more of the child component. I don't see any issues with the code provided. However as one improvement, you already have the `todo.id`, so you don't need to do the `currentTarget` stuff, just use the ID directly. – Brian Thompson Dec 15 '21 at 22:18
  • Agreed, not enough context to see why removing a todo isn't updating in the UI. Also, with the todo id there's no need to iterate the todos array 3 times to remove an element, that's what `Array.prototype.filter` is for . Can you update your question to include a more comprehensive [minimal, complete, and reproducible code example](https://stackoverflow.com/help/minimal-reproducible-example)? – Drew Reese Dec 16 '21 at 05:44
  • Hello! I found my problem: on my child component I was firing two events that eventually were leeading to a state change, therefore my two events were competing with each other. Solution was to use `event.stopPropagation()` – ihatepineapple Dec 16 '21 at 15:30

1 Answers1

0

Problem was on the child component


    const handleClick = (event) => {
        event.preventDefault()
        handleToggleComplete(event.currentTarget.id)
    }

    const handleDelete = (event) => {
        event.preventDefault()
        event.stopPropagation()
        deleteItem(event.currentTarget.parentNode.id)
    }


    return (
        <div id={todo.id} onClick={handleClick} className={todo.complete ? "todo strike" : "todo"}>
            {todo.task}
            <button onClick={handleDelete}>Delete</button>
        </div>
    );
 };

Clicking the delete button was also triggering a change of status (complete/incomplete), since the event was firing from the same source, same id etc. Solution was event.stopPropagation() on the handleDelete method.