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 2
vdom1
已创建
line 4
vdom2
被创建
比较vdom1
和vdom2
差异传播到实际的 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】:创建一个不可变的状态克隆是一个好主意,因为通过比较状态变化来优化渲染。
在shouldComponentUpdate
、nextProps
等生命周期方法中,传入并可以与this.props
进行比较。
如果您直接改变状态,那么 nextProps.prop1
和 this.props.prop1
将始终相同,因此您可能无法获得预期的行为。
我敢肯定还有其他原因,但这个原因似乎是最直接的。
【讨论】:
那么如果我不使用shouldComponentUpdate
那么就没有问题了?
还有其他生命周期方法也可用于比较道具(如componentWillReceiveProps
、componentWillUpdate
和componentDidUpdate
)。并且需要注意的是,你可能不会现在使用这些,而是希望稍后在事情变得缓慢时使用。
因此,如果我不使用任何生命周期方法,那很好,但是如果我想比较新旧状态/道具(任何地方),那么我不能直接改变状态。正确的 ?我的意思是,这取决于我做什么。如果我自己不比较新旧状态/道具,那很好,react 永远不会想要比较新旧状态/道具本身,对吧?因此,默认情况下,React 没有隐藏的魔法来尝试比较新旧状态。对吧?
说实话,我不是 100% 确定 React 内部使用了这个。 vdom 或 diffing 算法也可以假设状态不一样。
好吧,有趣!谢谢!以上是关于React 的 setState(),嵌套结构的数据变异,为啥不直接修改状态呢?的主要内容,如果未能解决你的问题,请参考以下文章
ES6/React:为啥我的三重嵌套 setState 更新不起作用?
React setState - 将数组添加到具有多个数组的嵌套对象
在 componentWillUpdate 或 componentDidUpdate 中重复调用 setState。 React 限制嵌套更新的数量以防止无限循环