【问题标题】:Updating state - why creating a new copy of state when calling setState?更新状态 - 为什么在调用 setState 时创建新的状态副本?
【发布时间】:2020-03-13 01:09:42
【问题描述】:

反应文档:

永远不要直接改变this.state,因为之后调用setState() 可能会替换您所做的突变。像对待this.state 一样对待 不可变。

这很清楚。

class App extends React.Component {
  state = {
   data: []
  } 

以下我理解

  updateState(event) {
   const {name, value} = event.target;
   let user = this.state.user; // this is a reference, not a copy...
   user[name] = value; // 
   return this.setState({user}); // so this could replace the previous mutation
  }

下面这个我看不懂

  updateState(event) {
  const {name, value} = event.target;
  let user = {...this.state.user, [name]: value};
  this.setState({user});
  }

我明白(如前面的例子),我不应该只是:

  1. 不调用setState直接改变状态;或
  2. 对其进行变异,然后使用 setState。

但是,为什么我不能(没有直接突变)调用 setState 而不创建一个新的状态副本(没有传播运算符/Object.assign)?以下会有什么问题:

  getData = () => {
   axios.get("example.com") ...
    this.setState({
     data:response.data
    })
  } 

为什么会这样:

  getData = () => {
   axios.get("example.com") ...
    this.setState({
     data:[...data, response.data]
    })
  } 

 render (){ 
  ...
 }  
}

【问题讨论】:

  • 因为在您的示例中您想将响应数据添加到数组的末尾,而不是用它替换数组?它们根本不等价,这与突变问题是分开的。
  • 您这样做是因为您只需要处理新的数据实例。这些新实例是根据前一个实例结合新数据创建的。

标签: reactjs immutability


【解决方案1】:

以下会有什么问题:

this.setState({
   data: response.data,
});

绝对没有,除非您不想将this.state.data 的内容替换为response.data

为什么会这样:

this.setState({
   data: [...data, response.data],
});

因为通过传播,您不会丢失 this.state.data 的内容 - 您基本上是在将新响应推送到 data 数组中。

注意:您应该在setState 中使用回调来从this.state 访问当前的data

this.setState((prevState) => ({
   data: [...prevState.data, response.data],
}));

【讨论】:

  • 啊,好的,我现在明白了。创建状态的副本仅适用于我想要添加而不是替换某些内容到数组或对象的情况。谢谢!!
  • @javascripting:如果它与 React 中的状态相关,请记住避免变异函数。你真的不想使用例如pushsplice 直接在状态上操作时。您必须使用其他一些不会发生变异并返回新实例的函数,例如sliceconcat 或传播语法。
  • @javascripting 或者基本上先创建一个深层副本,然后您就可以在该副本上使用变异函数,而不会有直接改变状态的风险。
  • 另外,我还有一个问题。使用 spad operator/Object.assign 或 concat 等仅在其不是更深的嵌套状态时才有效。例如: var state = { _2ndLevel: { arr: [] } } --> 在这种情况下,嵌套对象仍然会被引用,所以我最终会直接改变状态。在这里做什么有好处(不使用任何不变性库助手)?谢谢!!
  • @javascripting 在深度状态的情况下,你只需要更深入;) 解构整个状态,直到你到达它的指定部分。无论如何,是的,最好保持状态尽可能平坦。
猜你喜欢
  • 2019-01-05
  • 1970-01-01
  • 1970-01-01
  • 2017-09-16
  • 2018-12-08
  • 2020-10-04
  • 1970-01-01
  • 1970-01-01
  • 2022-08-14
相关资源
最近更新 更多