Removing an item causes React to remove the last DOM node instead of the one associated with that item

后端 未结 1 1154
轮回少年
轮回少年 2020-12-05 15:11

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

1条回答
  •  借酒劲吻你
    2020-12-05 15:44

    You're experiencing this problem because you're using index as your key:

    let nodes = items.map((item, index) => {
      let idx = index
      return ()
    })
    

    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];
    
    
  • 2
  • 4
  • 6
  • 8
  • 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];
    
    
  • 2
  • 4
  • 8
  • 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 ()
        })
    
        // ...
      }
    }
    

    Working example: http://jsbin.com/higofuhuni/2/edit

    0 讨论(0)
提交回复
热议问题