2015-08-20 79 views
4

我读过关于setState的ReactJS文档。具体来说,这一行: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开发团队骂吗?理想情况下,我想避免不可修复助手和所有其他疯狂并保持简单。

+0

改为使用this.forceUpdate()。或者使用React.addons.update来实现相同的结果。 –

+0

事情现在可能似乎有效。但是,这很可能会让位于稍后难以调试的问题。不可变规则确实是(强烈的)鼓励,决不允许组件访问比它需要更多的信息。如果你的组件需要知道xyz,而不是x或xy,那么在你的状态'var z = this.state.z'和'this.setState({z:z.concat(['foo'])} )'(通过道具初始化z)。如果外部世界需要知道z中的更改,则派发一个更改事件,以便触发父组件中x的更新或触发更新存储的操作。 – widged

回答

3

原因是你错过了与this.setState相关的回调,他们声称你可以通过直接指定对象来覆盖数据。另外,通常在OOP(我不知道有多少星星JS会得到...),你将使用getter和setter方法,而不是直接操纵对象。在这个例子中通过this.state.prop1 = "xyz";

我从来没有反应覆盖我的直接设置状态属性。以这种方式对其进行编码的诱惑可能是写入状态而不重新呈现。但如果你这样做,你可能会考虑不把它们放在状态中。

如果再渲染性能是一个问题检出https://facebook.github.io/react/docs/component-specs.html#updating-shouldcomponentupdate

+1

这是正确的^^应该指出,如果你直接操纵状态,那么你必须跟踪哪些数据已经处于状态,这可能变得单调乏味。补丁模式更容易维护,这是setState函数执行的内容。 – BentOnCoding

4

通过直接操作状态,你是绕过作出反应的状态管理,这还真管用反对阵营的范例。 React的setState最显着的好处是它会立即触发一个重新渲染,它将您的DOM更改从影子DOM合并到文档DOM中。因此,您可以捕获某些处理程序中需要的所有状态更改,然后在字面对象中构建所需的状态更改,然后将其传递至setState。这不是你上面的例子。

因此,尽管代码示例您提供技术上打破了这种规则,因为你通过一个状态对象属性的引用变异后直接调用setState,您的更改会立即正在通过漏斗作出反应的状态管理。所以,一切都会像你期望的那样工作。这个想法是,你不想养成用这种方式进行状态许多改变的习惯,最好是将你想要的状态捕获到一个新的文字对象或数组中,然后将它设置为一次状态(即,用没有以前的状态变化)通过调用setState,这将触发一次重新渲染。

编辑:为了更明确地回答你的问题,我想补充一点,真正令人担忧的是,开发将直接操纵状态在许多不同的地方或方法,没有调用setState,然后在以后的某个点或其他代码,请致电setState,然后想知道为什么他们的渲染没有产生他们预期的结果。由于setState对象合并了之间的已知,托管状态和作为参数传递到setState的文字对象,如果您以前曾经直接操纵状态,结果可能不会是你所期望的。

+0

您是否有此信息的来源/链接?我有兴趣了解如何调用setState触发重新渲染。 – BentOnCoding

+1

https://facebook.github.io/react/docs/interactivity-and-dynamic-uis.html#how-state-works – stolli

+1

感谢您的回复。为了澄清,我仅在对状态对象进行所有更改后才调用setState。 关于结果如何不能成为我期望的问题 - 这就是我想要深入研究的问题。结果如何出错? – mathew

-1

主要原因是shouldComponentUpdate不能正常工作。

相关问题