删除项会导致React删除最后一个DOM节点,而不是与该项相关联的DOM节点 [英] Removing an item causes React to remove the last DOM node instead of the one associated with that item
问题描述
我试图用ReactCSSTransitionGroup动画列表插入和删除,但是删除动画总是只动画列表的最后一个项目,而不是被删除的。
这里有一个jsbin来说明这个问题。尝试按添加按钮以验证插入动画确实按预期工作,然后单击除了任何项目之外的x,以查看列表的最后一项是动画,而不是您尝试删除的问题。
在设置TransitionGroup时我做错了,或者我在CSS转换定义中缺少了一些东西?
您遇到这个问题,因为您使用 index
p>
let nodes = items.map((item,index)=> {
let idx = index
return(< Item key = {index} value = {item} index = {index} _delete = {this._onDelete} />)
})
React在虚拟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
。 / p>
解决方案是为列表中的每个项目使用唯一的标识符;在实际应用程序中,您可能有 id
字段或其他主键要使用;对于像这样的应用程序,您可以生成一个增量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
I was trying to animate list insertion and removal with ReactCSSTransitionGroup, but the removal animation always animates only the last item of the list instead of the one that's being removed.
Here's a jsbin to illustrate this problem. Try pressing the "Add" button to verify that the insertion animation indeed works as expected, then click on the "x" besides any item to see the problem where the last item of the list is animated instead of the one you tried to remove.
Did I do something wrong while setting up the TransitionGroup or am I missing something in the CSS transition definitions?
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
这篇关于删除项会导致React删除最后一个DOM节点,而不是与该项相关联的DOM节点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!