React 应该组件更新没有检测到数组长度变化?



当更改通过props传递的数组的长度时,'shouldComponentUpdate'函数无法检测到数组长度的变化。我知道"shouldComponentUpdate"无法检测嵌套对象属性的更改,但这是一个简单的数组长度!!这是React中的一个bug吗??

https://jsfiddle.net/ashraffayad/cLz1q8sv/

var ArrTest = React.createClass({
  render: function() {
    return <div >{this.props.arr}< /div>;
  },
  shouldComponentUpdate: function(nextProps) {
    console.log(this.props.arr.length, nextProps.arr.length); // same length !!!
    return true;
  }
});
// - - - - app component
var App = React.createClass({
  getInitialState: function() {
    return {
      arr: [1, 2, 3, 4]
    };
  },
  render: function() {
    return <ArrTest arr={ this.state.arr } />;
  },
  componentDidMount: function() {
    var self = this;
    setTimeout(function() {
      self.state.arr.push(7);
      self.setState(self.state);
    }, 2000);
  }
});
ReactDOM.render( < App /> ,
  document.getElementById('container')
);

这不是React中的错误,而是代码的问题。永远不要直接修改this.state值。

试试这个:

  componentDidMount: function() {
    var self = this;
    setTimeout(function() {
      self.setState({arr: self.state.arr.concat([7])});
    }, 2000);
  }

它有效。因为React在传递道具时不会克隆道具,所以对数组的更改会反映在它的所有引用上。

我建议您在Javascript中阅读更多关于不变性的内容。

简而言之,永远不要做this.state.[anything].push/pop/shift/unshift(),永远不要。改为这样做:

var arr = this.state.arr.slice(); // Create a copy of the array
arr.push(2); // do whatever you want to do
this.setState({ arr: arr }); // pass changes to React

仅仅因为有两个引用(this.props.arrnextProps.arr)并不意味着有两个实例

当您使用push更改数组时,您将修改实例。当shouldComponentUpdate运行时,它会比较引用,因为它们指向同一个实例,所以数组长度是相同的。

如果你想传递一个具有不同元素或属性的新数组,那么你也需要创建一个新数组。

push代替concat是很容易的。

setTimeout(function() {
  self.setState({
    arr: self.state.concat([7])
}, 2000);

您在if中引用了相同的数组,即,您正在修改相同的数组而不是创建新的数组,并且您正在shouldComponentUpdate中处理对相同数组的两个引用。

您应该始终将props和state视为不可变的,因此使用.concat创建一个新数组,而不是推到处于状态的数组上,可以解决当前的问题。

setTimeout(function () {
    this.setState({arr: this.state.concat([7])});
}.bind(this), 2000);

如果您在shouldComponentUpdate中执行this.props.arr === nextProps.arr,您会看到数组将彼此相等。

最新更新