Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
ReactJS:为什么不应该';我不能改变嵌套状态吗?_Reactjs - Fatal编程技术网

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

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}); 此代码似乎可以正常工作并正确更新状态。但根据文件,我违反了规则。这种方法有什么问题?是否存在性能问题?

我已经阅读了关于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开发团队责骂吗?理想情况下,我希望避免不变性助手和所有其他疯狂行为,让事情变得简单。

原因是您错过了与此相关的回调。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,请在您的状态中设置z
var z=this.state.z
this.setState({z:z.concat(['foo'])})
(通过props初始化z)。如果外部世界需要了解z中的更改,则发送一个更改事件,该事件将触发父组件中x的更新,或触发一个将更新存储的操作。这是正确的^^应该注意的是,如果直接操作状态,则必须跟踪哪些数据已处于状态,这可能会变得乏味。补丁模式更容易维护,这是setState函数强制执行的。您有此信息的源/链接吗?我很想了解调用setState如何触发重新渲染。感谢您的回复。为了澄清,我只在对state对象进行了所有更改之后调用setState。关于结果如何不符合我的预期的问题——这就是我试图深入研究的问题。结果怎么会出错呢?我们的想法是,你可以改变状态,然后进行一个
setState
调用,该调用不包括你以前的突变,并从本质上覆盖它们,然后混淆你为什么没有得到预期的结果。然而,正如我们所讨论的,在上面的使用模式中,这种情况不太可能发生。