javascript 为什么会出现此错误:“不变违规:无法在现有状态转换期间更新”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31420402/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 13:45:57  来源:igfitidea点击:

Why does this error exist: "Invariant Violation: Cannot update during an existing state transition"

javascriptreactjsreact-native

提问by jameslk

I seem to be running into this error in a large application (but I'm not exactly sure where):

我似乎在大型应用程序中遇到了这个错误(但我不确定在哪里):

Uncaught Error: Invariant Violation: setState(...): Cannot update during an existing state transition (such as within render). Render methods should be a pure function of props and state.

未捕获的错误:不变违规:setState(...):无法在现有状态转换期间更新(例如在 内render)。Render 方法应该是 props 和 state 的纯函数。

I suspect it might be the result of using setStateinside of setTimeoutor setInterval.

我怀疑这可能是在orsetState内部使用的结果。setTimeoutsetInterval

Which leads me to my real question: why does this error exist? Is there some conceptual reason I'm missing why ReactJS doesn't just queue state and prop changes? I'm guessing if there is a reason, it has to do with application complexity and/or avoiding race conditions...

这让我想到了我真正的问题:为什么会存在这个错误?是否有一些概念上的原因我想念为什么 ReactJS 不只是排队状态和道具更改?我猜是否有原因,它与应用程序复杂性和/或避免竞争条件有关...

My next question then would be: what is the proper way to update a component outside of React (during some asynchronous event for example) so that this error doesn't occur?

我的下一个问题是:在 React 之外更新组件的正确方法是什么(例如在某些异步事件期间),以便不会发生此错误?

Edit:

编辑:

After some digging into this issue further, it appears the culprit is actually the underlying platform I'm using (ElectronJS, formally Atom Shell). Basically, ElectronJS combines Chromium and NodeJS together. I was using a NodeJS API to do something asynchronous and it appears when that finished, ElectronJS would just return back to the call stack where it left off, bypassing the event loop altogether and thus causing a race condition with React.

在进一步深入研究这个问题之后,看来罪魁祸首实际上是我正在使用的底层平台(ElectronJS,正式的 Atom Shell)。基本上,ElectronJS 将 Chromium 和 NodeJS 结合在一起。我正在使用 NodeJS API 来做一些异步的事情,当它完成时,ElectronJS 只会返回到它停止的调用堆栈,完全绕过事件循环,从而导致与 React 的竞争条件。

回答by Hannes Johansson

The issue is that setStatewill cause a re-render (potentially, depending on shouldComponentUpdate). If you had a setStatecall within the renderfunction, it would trigger yet another render. You'd likely end up in an infinite loop of re-renderings. There's nothing that stops you from using setStateas a result of some asynchronous operation (in fact it's very common). It's fine just as long as it's not in the renderor some other lifecycle method of a component that is run on a state update (shouldComponentUpdatebeing another as you'd end up with an infinite loop in the same way).

问题是这setState会导致重新渲染(可能取决于shouldComponentUpdate)。如果您setStaterender函数内进行了调用,它将触发另一个渲染。您可能会陷入无限循环的重新渲染。setState由于某些异步操作,没有什么可以阻止您使用(实际上它很常见)。只要它不在render状态更新上运行的组件的生命周期方法或其他生命周期方法中就可以了(这shouldComponentUpdate是另一个,因为您最终会以相同的方式进入无限循环)。

回答by edoloughlin

One way to achieve this is to use the Flux pattern and have your timeouts trigger changes in a store. This will cause the changes to propagate to interested components as part of their lifecycle.

实现此目的的一种方法是使用 Flux 模式并让您的超时触发商店中的更改。这将导致更改传播到感兴趣的组件作为其生命周期的一部分。