Не удается редактировать state в React. Encountered two children with the same key, `(id элемента)`

Рейтинг: 1Ответов: 0Опубликовано: 27.05.2023

Я делаю to do приложение, и мне надо, чтобы по кнопке "clear completed" обновлялся state в компоненте app.

Задумка:

Есть state в компоненте app, где хранится информация о задачах в виде списка. При каждом нажатии на чекбокс стейт обновляется по id элемента, и переменная isEnd определенного элемента обновляется на состояние его чекбокса. По нажатию кнопки "clear completed" происходит фильтрация стейта, где пачкой удаляются те элементы, которые соответствуют условию isEnd == true. Данная фильтрация присваивается новому элементу, а он, в свою очередь, передается в this.setState({todos: newListTodos}). Список элементов отображается при помощи функции .map((~) => {~}). Каждому элементу присвается key={todo.id} Такая вот задумка.

Проблема:

При первом удалении все происходит абсолютно корректно, но далее после нажатия на чекбокс задача дублируется, и в консоли пишется: Encountered two children with the same key, (id элемента). Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — the behavior is unsupported and could change in a future version. Помимо этого, переменная newListTodos корректно обновляется, а сам стейт остается прежним.

Путь решения:

И в интернете, и в документации React говорится о том, что при каждом изменении стейта нужно передавать новый объект не напрямую и иметь старый объект, чтобы реакту было с чем сравнивать новый объект. Но старый объект поимел меня. Я не знаю как реализовать метод корректного обновления стейта.

App.js:

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      all: true,
      active: false,
      completed: false,
      todos: [{
          text: "Complete online JavaScript course",
          isEnd: true,
          id: 0,
        },
        {
          text: "Jog around the park 3x",
          isEnd: false,
          id: 1,
        },
        {
          text: "10 minutes meditation",
          isEnd: false,
          id: 2,
        },
        {
          text: "Read for 1 hour",
          isEnd: false,
          id: 3,
        },
        {
          text: "Pick up groceries",
          isEnd: false,
          id: 4,
        },
        {
          text: "Complete Todo App on Frontend Mentor",
          isEnd: false,
          id: 5,
        },
      ],
    };

    this.clearCompleted = this.clearCompleted.bind(this)
  }

  //вывод контента

  clearCompleted() {
    const newListTodos = this.state.todos.filter((element) => element.isEnd === false)
    this.setState({
      todos: newListTodos
    })
  }
}

listToDo.js:

class listToDo extends React.Component {
  render() {
    if (this.props.todos.length > 0)
      return (
        <div className="list-todos">
          {this.props.todos.map((this_toDo) => (
            <ToDo key={this_toDo.id} updateCount={this.props.updateCount} todoInfo={this_toDo} />
          ))}
        </div>
      );
    else
      return (
        <div>
          <h2 className="grey">List a void.</h2>
        </div>
      );
  }
}

Может эта проблема и покажется банальной, но для меня, как для новичка в реакт, это вызывает трудности.

Ответы

Ответов пока нет.