Проблема с удалением элемента из списка

#reactjs

#reactjs

Вопрос:

Я пытаюсь создать список дел, из которого я удаляю элементы и меняю их статус на завершено. Когда я нажимаю флажок элемента, он удаляет только первый элемент, а когда я пытаюсь изменить статус элемента на завершено, он сообщает, что этот элемент не существует. Поэтому я предполагаю, что это проблема с индексом элемента, который я передаю в функцию удаления. Буду признателен за любую помощь, спасибо.

Это объекты todo:

 const [todos, setTodos] = useState([
    {
      text: "Learn about React",
      isCompleted: true
    },
    {
      text: "Meet friend for lunch",
      isCompleted: false
    },
    {
      text: "Wash Dishes",
      isCompleted: false
    }
  ]);
  

Это то, что вызывается, когда я удаляю элемент

 const removeTodo = index => {
    const checkTodos = [...todos];         //The list is copied and isCompleted is changed to true
    checkTodos[index].isCompleted = true;  //This line results in: 
    setTodos(checkTodos);                  //Cannot set property 'isCompleted' of undefined

    const newTodos = [...todos];           //Here is where I remove from the list
    newTodos.splice(index, 1);             //I remove the specific index but it deletes only the first 
    setTodos(newTodos);                    //item no matter where I click
  };
  

Вот как я вызываю функцию удаления

 <div style = {{paddingTop: 40}}>
  <List>
    {todos.map((value) => {
      return(
        <ListItem>
          <ListItemIcon>
            <Checkbox
              edge="start"
              checked={value.isCompleted}
              onChange={removeTodo}         //Remove function is called here 
              tabIndex={-1}
              disableRipple
            />
          </ListItemIcon>
          <ListItemText disableTypography style={{fontFamily: 'Work Sans', fontSize: 35}} primary={value.text}/>
        </ListItem>
      );
    })}
  </List>
</div>
  

Комментарии:

1. Во-первых, вы фактически не передаете индекс removeTodo функции, так как же она узнает, на какую из них вы ссылаетесь? Кроме того, если вы имеете дело с динамическим списком (добавление / удаление элементов), вы не можете использовать индекс в качестве идентификатора. Им нужно что-то уникальное

2. @pilchard: разве это не должно быть onChange={() => removeTodo(index)} ?

3. да, но, увы, слишком поздно его редактировать.

4. Я согласен с Jayce444 в том, что вы должны использовать какой-то уникальный идентификатор для ссылки на todos, но чтобы получить то, что у вас работает, попробуйте передать index из map в onChange… {todos.map((value, index) => { ... <Checkbox onChange={() => removeTodo(index)}>...}

5. вы добавили индекс к переданным аргументам из map() ? {todos.map((value, index) =>

Ответ №1:

В react, если вы используете Map, вы должны предоставить ключ своим дочерним элементам, чтобы он мог однозначно идентифицировать все. Затем вызовите removeTodo с индексом, чтобы удалить его должным образом.

 <div style = {{paddingTop: 40}}>
  <List>
    {todos.map((value, index) => {
      return(
        <ListItem key={value}>
          <ListItemIcon>
            <Checkbox
              edge="start"
              checked={value.isCompleted}
              onChange={() => removeTodo(index)}          
              tabIndex={-1}
              disableRipple
            />
          </ListItemIcon>
          <ListItemText disableTypography style={{fontFamily: 'Work Sans', fontSize: 35}} primary={value.text}/>
        </ListItem>
      );
    })}
  </List>
</div>