You're experiencing this problem because you're using index
as your key:
let nodes = items.map((item, index) => {
let idx = index
return (<Item key={index} value={item} index={index} _delete={this._onDelete}/>)
})
React uses the key
property during virtual DOM diffing to figure out which element was removed, but indexes will never serve this purpose sufficiently.
Consider this example: you start off with the following array, which results in the following DOM structure:
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>
Then imagine you remove the element at index 2
. You now have the following array, and the following DOM structure:
const arr = [2, 4, 8];
<li key={0}>2</li>
<li key={1}>4</li>
<li key={2}>8</li>
Notice that the 8
now resides in index 2
; React sees that the difference between this DOM structure and the last one is that the li
with key 3
is missing, so it removes it. So, no matter which array element you removed, the resulting DOM structure will be missing the li
with key 3
.
The solution is to use a unique identifier for each item in the list; in a real-life application, you might have an id
field or some other primary key to use; for an app like this one, you can generate a incrementing 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}/>)
})
// ...
}
}
Working example: http://jsbin.com/higofuhuni/2/edit
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…