删除项会导致React删除最后一个DOM节点,而不是与该项相关联的DOM节点 [英] Removing an item causes React to remove the last DOM node instead of the one associated with that item

查看:982
本文介绍了删除项会导致React删除最后一个DOM节点,而不是与该项相关联的DOM节点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆