React的差异算法如何与元素列表一起工作?

时间:2018-11-12 12:54:43

标签: javascript reactjs

UPD: 我使用了具有突出显示更新的React Dev Tools,它似乎突出显示了每个render()方法调用

我已经编写了一个简单的React App,它的工作方式如下:

  1. 它有一个按钮和一个数字列表
  2. 点击按钮后,它会在列表底部添加一个新数字,比上一个数字增加1。

问题在于,即使我使用key属性, React也会每次更新所有列表元素。我知道可以使用PureComponents类或自行实现的shouldComponentUpdate()

解决此问题

如果没有更改,为什么React会更新所有列表元素?我虽然说React使用特殊的 diffing算法来比较元素,它应该可以工作,但是现在我发现它不能按我的预期工作。

有谁能解释为什么React的差异算法在这种情况下不起作用?

class App extends Component {
  constructor(props) {
    super(props);

    this.state = {
      numbers: [] 
    }

    this.handleButtonClick = this.handleButtonClick.bind(this);
  }

  handleButtonClick() {
    const numbers = this.state.numbers;
    const length = this.state.numbers.length ;
    const newNumber = length > 0 ? numbers[length - 1] + 1 : 0;

    this.setState({
      numbers: [...numbers, newNumber]
    })
  }

  render() {
    return (
      <div>
        <button onClick={this.handleButtonClick}>Add</button>
        <NumbersList numbers={this.state.numbers} />
      </div>
    );
  }
}


class NumbersList extends Component {
  render() {
    return (
      <ul>
        {
          this.props.numbers.map((number) => <NumberItem key={number} number={number} />)
        }
      </ul>
    )
  }
}

class NumberItem extends Component {
  render() {
    return (
      <li>{this.props.number}</li>
    )
  }
}

2 个答案:

答案 0 :(得分:1)

Javascript / React端使用shouldComponentUpdate来确定是否应重新呈现。此默认设置为true,并在状态更改时重新渲染组件。

https://reactjs.org/docs/react-component.html#shouldcomponentupdate

使用此重新呈现的应用程序虚拟表示形式,它使用此https://reactjs.org/docs/reconciliation.html#the-diffing-algorithm将您的virtualDOM与真实DOM调和

答案 1 :(得分:0)

您尝试过吗:

this.setState({numbers[index-1]: newNumber})

您的代码在这里:

this.setState({
  numbers: [...numbers, newNumber]
})

在我看来是替换数字数组,而不是更新它。