Не удается редактировать state в React. Encountered two children with the same key, `(id элемента)`
Я делаю 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>
);
}
}
Может эта проблема и покажется банальной, но для меня, как для новичка в реакт, это вызывает трудности.