最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

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

programmeradmin1浏览0评论

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.

I suspect it might be the result of using setState inside of setTimeout or setInterval.

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...

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?

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.

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.

I suspect it might be the result of using setState inside of setTimeout or setInterval.

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...

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?

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.

Share Improve this question edited Mar 31, 2016 at 4:29 Tony Peng 132 bronze badges asked Jul 15, 2015 at 2:16 jameslkjameslk 4,8284 gold badges22 silver badges19 bronze badges 5
  • React will, if neccessary, batch setState calls. – Henrik Andersson Commented Jul 15, 2015 at 4:57
  • Hi jameslk, I got the same issue with React + Electron, and the error keep showing. Seems that it will not break the app but still quite annoying. Have you figure out a way to fix that? – fraserxu Commented Oct 14, 2015 at 7:03
  • 2 Got something working with setImmediate( // the function that may call setState) – fraserxu Commented Oct 14, 2015 at 7:16
  • 2 @fraserxv My solutions was similar. It was originating from the library request.js, which uses the node http library underneath. I basically had to put a setTimeout of 0 (same as setImmediate) inside the response callback and the problem went away. – jameslk Commented Oct 14, 2015 at 23:15
  • FYI, I reported the issue on Electron's Github a while back but it was left as a wontfix. "In Electron the task queue of Node.js and the task queue of browser are independent, so there is no guarantee that tasks of setTimeout and Node.js APIs would run in sequence. Also the web standard never guarantees the sequence of setTimeout callbacks, so I think current behavior is fine." Here's the specific issue: github.com/atom/electron/issues/2239 – jameslk Commented Oct 14, 2015 at 23:25
Add a comment  | 

2 Answers 2

Reset to default 20

The issue is that setState will cause a re-render (potentially, depending on shouldComponentUpdate). If you had a setState call within the render function, 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 setState as a result of some asynchronous operation (in fact it's very common). It's fine just as long as it's not in the render or some other lifecycle method of a component that is run on a state update (shouldComponentUpdate being another as you'd end up with an infinite loop in the same way).

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.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论