这样重写React状态数组好吗?

时间:2018-10-19 06:56:43

标签: javascript reactjs react-native

请这不是重复的问题。我的问题是,如果将状态数组分配给局部变量并将值推入局部变量,是否会引起错误。

我陷入困境,了解将值推入React状态数组或覆盖值时哪个是正确的。

根据React文档,以下代码风格不好,并会导致错误

   this.state = {
        list: []
  }

  componentDidMount(){
      const { list } = this.state;
      list.push(“test”);//this is bad style of pushing values into React state and causes a bug
      this.setState({list});
 }

如果我在下面这样做,会导致错误吗?将状态列表分配给局部变量,并将值推入该局部变量,并将数组的状态设置为list。这和上面的代码一样吗?

  this.state = {
        list: []
  }
  componentDidMount(){
      const { list } = this.state;
      const array = list;
      array.push(“test”); //pushing values to a local variable  too a bad style and causes a bug in React?
      this.setState({list: array});
 }

4 个答案:

答案 0 :(得分:4)

是的,您的第二种方法也会导致错误,因为状态数组在此阶段被更新{array.push(“ test”); }。而且,如果您的类是PureComponent,那么它将不会重新渲染。

所以你可以尝试

 const list = [... this.state.list];

OR

 const list = this.state.list.slice();

以这种方式创建数组的副本。

您的新代码如下所示:-

const list = [... this.state.list];
list.push("new value");
this.setState({ list });

答案 1 :(得分:3)

您的第一个示例实际上并不是React错误,我不确定它完全可以视为Bug。 Array.prototype.push()改变了数组,这是您要在React中避免的事情(不要直接修改状态)。

很显然,您可以使用Array.prototype.slice()

来完成第二个示例中的操作
let newList = this.state.list.slice();
newList.push(someValue);

this.setState({ list: newList })

另一种选择是简单地在您的Array.prototype.concat()中使用setState()方向

this.setState({ list: this.state.list.concat(someValue)})

我想这是我现在想到的选择。

答案 2 :(得分:3)

这不是错误,而是预期的行为。状态不应该被改变。

问题中的两个代码段是相同的,数组是对象,并且对象是通过JavaScript引用传递的,因此无论是list还是array被突变。

list数组应该是不可变的,即,如果需要对其进行更改,则会创建一个新的数组。

此外,在this.state中使用this.setState的值是antipattern

  

setState()并不总是立即更新组件。它可能会批量更新或将更新推迟到以后。这使得在调用setState()之后立即读取this.state可能是一个陷阱。而是使用componentDidUpdate或setState回调(setState(updater,callback)),确保在应用更新后均能触发这两种方法。如果需要基于先前的状态来设置状态,请阅读以下有关updater参数的信息。

应使用更新程序功能:

componentDidMount(){
  this.setState(({ list }) => ({ list: [...list, 'test'] }));
}

答案 3 :(得分:2)

this.setState({ list:[..this.state.list,'new value'] });

您可以直接使用传播运算符设置setState ..希望它可以工作