Ответ 1
У вас возникла эта проблема, потому что вы используете index
в качестве своего ключа:
let nodes = items.map((item, index) => {
let idx = index
return (<Item key={index} value={item} index={index} _delete={this._onDelete}/>)
})
React использует свойство key
во время виртуальной DOM, чтобы выяснить, какой элемент был удален, но индексы никогда не будут служить этой цели достаточно.
Рассмотрим этот пример: вы начинаете со следующего массива, что приводит к следующей структуре DOM:
const arr = [2, 4, 6, 8];
<li key={0}>2</li>
<li key={1}>4</li>
<li key={2}>6</li>
<li key={3}>8</li>
Тогда представьте, что вы удаляете элемент по индексу 2
. Теперь у вас есть следующий массив и следующая структура DOM:
const arr = [2, 4, 8];
<li key={0}>2</li>
<li key={1}>4</li>
<li key={2}>8</li>
Обратите внимание, что 8
теперь находится в индексе 2
; React видит, что разница между этой структурой DOM и последней состоит в том, что отсутствует li
с ключом 3
, поэтому он удаляет его. Таким образом, независимо от того, какой элемент массива вы удалили, в результате структуры DOM будет отсутствовать li
с ключом 3
.
Решение состоит в использовании уникального идентификатора для каждого элемента в списке; в реальном приложении у вас может быть поле id
или какой-либо другой первичный ключ; для такого приложения, как этот, вы можете сгенерировать инкрементирующий идентификатор:
let id = 0;
class List extends Component {
constructor() {
this.state = {
items: [{id: ++id, value: 1}, {id: ++id, value: 2}]
}
// ...
}
_onClick(e) {
this.state.items.push({id: ++id, value: Math.round(Math.random() * 10)})
this.setState({items: this.state.items})
}
// ...
render() {
let items = this.state.items
let nodes = items.map((item, index) => {
let idx = index
return (<Item key={item.id} value={item.value} index={index} _delete={this._onDelete}/>)
})
// ...
}
}
Рабочий пример: http://jsbin.com/higofuhuni/2/edit