ReactJS:为什么我不应该改变嵌套状态?

时间:2015-08-20 17:52:14

标签: reactjs

我已阅读有关 setState 的ReactJS文档。具体来说,这一行:

  

不要直接改变this.state,因为之后调用setState()可能会替换你所做的突变。把this.state看作是不可变的。

但是在我的代码中,我做了这样的事情:

var x = this.state.x;
x.y.z.push("foo"); // z is a list
this.setState({x:x});

此代码似乎正常工作并正确更新状态。但根据文件,我违反了规则。这种方法有什么问题?有性能问题吗?比赛条件?我会被Facebook开发团队骂?理想情况下,我想避免不可变性助手和所有其他疯狂,并保持简单。

3 个答案:

答案 0 :(得分:5)

通过直接操纵状态,你正在规避React的状态管理,这对React范式起作用。 React的setState最显着的好处是它会立即触发重新渲染,将DOM中的DOM更改与shadow DOM合并到文档DOM中。因此,您捕获某个处理程序中所需的所有状态更改,然后在文字对象中构建所需的状态更改,然后将其传递给setState。这不是你上面的例子。

因此,虽然您提供的技术上的代码示例违反了此规则,但由于您在通过对状态对象属性的引用进行变更后直接调用setState,因此您的更改会立即通过反应的国家管理。所以,一切都会按预期工作。这个想法是你不想养成以这种方式对状态进行许多更改的习惯,最好在新的文字对象或数组中捕获你想要的状态,然后将其设置为通过调用setState状态一次(即没有先前的状态突变),这将触发单个重新渲染。

编辑:为了更明确地回答你的问题,我想补充一点,真正关心的是开发人员会在许多不同的地方或方法中直接操纵状态,没有调用setState,然后在某个稍后的点或其他代码中,调用setState,然后想知道为什么他们的渲染不会产生他们期望的结果。由于setState在已知的托管状态和作为参数传递给setState的文字对象之间执行了一个对象 merge ,因此结果可能不会是如果您之前曾直接操纵州,那么您会期待什么。

答案 1 :(得分:3)

原因是您错过了与this.setState相关联的回调,他们声称您可以通过直接指定对象来覆盖数据。

另外,经常在OOP中(我不知道JS有多少星......)你将使用getter和setter方法而不是直接操作对象。在此示例中,通过this.state.prop1 = "xyz";

我从来没有反应覆盖我直接设置的状态属性。以这种方式编码的诱惑可能是写入状态而无需重新渲染。但是,如果你这样做,你可能会考虑不要把它们放在州里。

如果重新呈现效果是问题结帐https://facebook.github.io/react/docs/component-specs.html#updating-shouldcomponentupdate

答案 2 :(得分:-1)

主要原因是shouldComponentUpdate无法正常工作。