-
Notifications
You must be signed in to change notification settings - Fork 47.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bug: infinite loop when a set state hook is called in a global handler #17918
Comments
I can confirm and reproduce this bug. |
Interesting. Looks like this has been reported before for people using the
Looks like that library just calls I'm not very familiar with our DOM event system so I don't know why this behavior would be happening, but as a temporary workaround for the issue, you can use a |
The print function is still sync in Chrome but not in Safari and that was our workaround for this (use case: modify some state for printing and revert after printing). It seems like the following mitigates the problem:
|
This does not match my testing a few minutes ago. Also, a duration of 100 shouldn't be necessary. 0 should work. I think you just need to move the state update outside of the context of the |
I believe the problem is happening is an event loop, right? In the first call of However the javascript reading continues and reads below and calling the And after that the event looping detects that there is something in the queue and executes setTimeout. Example: Here talking a little more about the topic. |
The behavior seems to be caused by the way react-dom's dev version handles errors in user-provided callbacks. For context: react/packages/shared/invokeGuardedCallbackImpl.js Lines 42 to 49 in da83408
Relevant to this issue: react/packages/shared/invokeGuardedCallbackImpl.js Lines 86 to 180 in da83408
Simply put, to play nicer with devtools, user-provided callbacks are not called directly. Instead a listener to a synthetic event is setup (L175), with its handler calling the user-provided callback (L130). Then the event is immediately dispatched (L180). For some reason, when a callback is invoked from within a Replacing this part: react/packages/shared/invokeGuardedCallbackImpl.js Lines 175 to 180 in da83408
... with just: callCallback(); ... prevents the faulty behavior from occuring. It's also worth nothing that this does not happen in production since callbacks are called directly. Working around this proves to be difficult, especially when trying to change state in response to |
I'm also having this issue, in conjunction with printing, and can corroborate @idmadj's analysis. There's an infinite loop in the dev implementation for Interestingly, a workaround in my case seems to be changing Further investigating reveals that this only seems to be an issue when programmatically invoking window.print(). https://codesandbox.io/s/nervous-liskov-3mqby Opening up the page outside of the sandbox, and pressing Ctrl+P reveals that the callback is invoked synchronously, and using |
Looks this this was actually fixed for React 17 in #19220. |
Last published build from master before #19220 was Closing since it the description fits. |
To be honest, I am not 100% sure it's a bug. Perhaps my code is badly written but I don't know why it's not working or how to rewrite it in the proper way.
React version: 16.12.0
Steps To Reproduce
Link to code example: https://jsfiddle.net/z4ku39t2/2
The current behavior
When the setS is called in the onafterprint handler, the app enters an infinite loop with 100% cpu usage so you won't be able to do anything on the page. The profiler shows that it happens inside React.
The expected behavior
The setS successfully modifies the state and the component re-renders.
Browser: Version 79.0.3945.130 (Official Build) (64-bit)
The text was updated successfully, but these errors were encountered: