ReactJS:为什么不应该';我不能改变嵌套状态吗?
我已经阅读了关于setState的ReactJS文档。具体而言,这一行: 切勿直接对this.state进行变异,因为之后调用setState()可能会替换您所做的变异。将this.state视为不可变的 但在我的代码中,我做的事情如下:ReactJS:为什么不应该';我不能改变嵌套状态吗?,reactjs,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}); 此代码似乎可以正常工作并正确更新状态。但根据文件,我违反了规则。这种方法有什么问题?是否存在性能问题?
var x = this.state.x;
x.y.z.push("foo"); // z is a list
this.setState({x:x});
此代码似乎可以正常工作并正确更新状态。但根据文件,我违反了规则。这种方法有什么问题?是否存在性能问题?比赛条件?我会被Facebook开发团队责骂吗?理想情况下,我希望避免不变性助手和所有其他疯狂行为,让事情变得简单。原因是您错过了与此相关的回调。setState,它们声称您可以通过直接分配给对象来覆盖数据 另外,在OOP中(我不知道JS得到了多少星星…),通常使用getter和setter方法,而不是直接操作对象。在本例中,通过
this.state.prop1=“xyz”代码>
我从来没有覆盖过直接设置的状态属性。以这种方式编写代码的诱惑可能是在不重新呈现的情况下写入状态。但如果你这样做的话,你可能会考虑无论如何不要把它们放在州里
如果通过直接操纵状态来重新呈现性能是一个问题,那么您就绕过了React的状态管理,而React的状态管理实际上与React范式背道而驰。React的setState
最显著的好处是它会立即触发重新渲染,从而将您的DOM更改从阴影DOM合并到文档DOM中。因此,您可以捕获某些处理程序中需要的所有状态更改,然后在文本对象中构建所需的状态更改,然后将其传递给setState
。这与上面的示例不同
因此,虽然您提供的代码示例在技术上违反了这一规则,但由于您在通过对状态对象属性的引用进行变异后直接调用setState
,因此您的更改会立即通过React的状态管理进行。所以,一切都会按照你的预期进行。这样做的想法是,您不想养成以这种方式对状态进行许多更改的习惯,最好在一个新的文本对象或数组中捕获您想要的状态,然后通过调用setState
,将其设置为状态一次(即,之前没有状态突变),这将触发一次重新渲染
编辑:为了更明确地回答您的问题,我想补充一点,真正的问题是开发人员将直接在许多不同的位置或方法中操作状态,而不调用setState
,然后在稍后的某个点或其他代码,调用setState
,然后想知道为什么他们的渲染没有产生预期的结果。由于setState
对象是否在已知的托管状态和作为参数传递给setState
的文本对象之间合并,如果您之前直接操作了状态,则结果可能不是您预期的结果。主要原因是shouldComponentUpdate无法正常工作。请改用此.forceUpdate()。或者使用React.addons.update来获得相同的结果。现在事情看起来可能正常了。然而,这很可能会让位于以后难以调试的问题。不变性规则实际上是一种(强烈的)鼓励,永远不要让组件访问超出其需要的更多信息。如果您的组件需要了解x.y.z,但不需要了解x或x.y,请在您的状态中设置zvar z=this.state.z
和this.setState({z:z.concat(['foo'])})
(通过props初始化z)。如果外部世界需要了解z中的更改,则发送一个更改事件,该事件将触发父组件中x的更新,或触发一个将更新存储的操作。这是正确的^^应该注意的是,如果直接操作状态,则必须跟踪哪些数据已处于状态,这可能会变得乏味。补丁模式更容易维护,这是setState函数强制执行的。您有此信息的源/链接吗?我很想了解调用setState如何触发重新渲染。感谢您的回复。为了澄清,我只在对state对象进行了所有更改之后调用setState。关于结果如何不符合我的预期的问题——这就是我试图深入研究的问题。结果怎么会出错呢?我们的想法是,你可以改变状态,然后进行一个setState
调用,该调用不包括你以前的突变,并从本质上覆盖它们,然后混淆你为什么没有得到预期的结果。然而,正如我们所讨论的,在上面的使用模式中,这种情况不太可能发生。