React 的 setState(),嵌套结构的数据变异,为啥不直接修改状态呢?

Posted

技术标签:

【中文标题】React 的 setState(),嵌套结构的数据变异,为啥不直接修改状态呢?【英文标题】:React's setState(), data mutation for nested structures, why not modify state directly?React 的 setState(),嵌套结构的数据变异,为什么不直接修改状态呢? 【发布时间】:2017-03-05 22:13:23 【问题描述】:

下面的反应代码错了吗?

state= foo:  bar: true    // line 1
setState(state)               // line 2   
state.foo.bar = false         // line 3
setState(state)               // line 4

如果是,为什么?

This提示错了,但没有解释为什么?

我认为没有错,原因如下:

line 2vdom1 已创建 line 4vdom2 被创建 比较vdom1vdom2 差异传播到实际的 DOM

如果是这种情况,那么在line3 处变异state 应该不会对line4 处发生的事情产生任何影响。

换句话说:

这应该是等效的代码:

state= foo:  bar: true    // line 1
setState(state)               // line 2   
state= foo:  bar: false   // line 3
setState(state)               // line 4

这段代码是否等同于上面的代码?

如果不是,为什么不呢?

【问题讨论】:

这似乎相关:***.com/questions/37755997/… 我悬赏这个相关问题:***.com/questions/37755997/… 这个也有关系***.com/questions/28300547/…但是没有给出答案 【参考方案1】:

创建一个不可变的状态克隆是一个好主意,因为通过比较状态变化来优化渲染。

shouldComponentUpdatenextProps 等生命周期方法中,传入并可以与this.props 进行比较。

如果您直接改变状态,那么 nextProps.prop1this.props.prop1 将始终相同,因此您可能无法获得预期的行为。

我敢肯定还有其他原因,但这个原因似乎是最直接的。

【讨论】:

那么如果我不使用shouldComponentUpdate那么就没有问题了? 还有其他生命周期方法也可用于比较道具(如componentWillReceivePropscomponentWillUpdatecomponentDidUpdate)。并且需要注意的是,你可能不会现在使用这些,而是希望稍后在事情变得缓慢时使用。 因此,如果我不使用任何生命周期方法,那很好,但是如果我想比较新旧状态/道具(任何地方),那么我不能直接改变状态。正确的 ?我的意思是,这取决于我做什么。如果我自己不比较新旧状态/道具,那很好,react 永远不会想要比较新旧状态/道具本身,对吧?因此,默认情况下,React 没有隐藏的魔法来尝试比较新旧状态。对吧? 说实话,我不是 100% 确定 React 内部使用了这个。 vdom 或 diffing 算法也可以假设状态不一样。 好吧,有趣!谢谢!

以上是关于React 的 setState(),嵌套结构的数据变异,为啥不直接修改状态呢?的主要内容,如果未能解决你的问题,请参考以下文章

ES6/React:为啥我的三重嵌套 setState 更新不起作用?

React setState - 将数组添加到具有多个数组的嵌套对象

在 componentWillUpdate 或 componentDidUpdate 中重复调用 setState。 React 限制嵌套更新的数量以防止无限循环

反应中嵌套数组中的setState

React:在 setState 中设置数组对象

Flutter 嵌套小部件 setState 无法按预期工作