Skip to content
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: Potential infinite loop with Suspense (and Error boundaries not triggered) #24634

Open
bvaughn opened this issue May 28, 2022 · 4 comments
Labels
Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug Type: Bug

Comments

@bvaughn
Copy link
Contributor

bvaughn commented May 28, 2022

React version: latest stable (and experimental)

Steps To Reproduce

  1. Checkout the following repo: https://github.com/bvaughn/react-suspense-error-boundary-bug
  2. Run npm install && npm run dev
  3. Load the browser and observe an infinite loop of components re-rendering (rather than the error boundary catching the error).

I've added a lot of inline comments about things that are necessary to trigger this bug in this file:
https://github.com/bvaughn/react-suspense-error-boundary-bug/blob/main/pages/index.js

Note that I was unable to reproduce this bug with Code Sandbox or Create React App. It only reproduces when running with Next JS (and only in DEV mode). Maybe it has something to do with Next's custom error logging behavior? Unfortunately there's no way to disable this (see vercel/next.js/discussions/13387) so I'm not sure.

@bvaughn bvaughn added Type: Bug Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug labels May 28, 2022
@Andarist
Copy link
Contributor

I'm pretty sure that I know what is the scenario here. This is about React trying to render many components in "parallel" - each of them could suspend after all and I suspect that React wants to "kick-off" all of them and a single caught error (that is not a promise) doesn't abort the computation. The problem is that this particular render won't be suspending at all - all of those "parallel" components throw here. And it takes time to go through all of them, in fact - it takes more than a "concurrent deadline". So when looping over work React finally recognizes that it should yield, and it does but when going back to the work loop... it starts from scratch. So the whole work done in the previous iteration of the work loop is lost here (probably that work that has thrown errors is not cached in your React's internal structures).

This can be verified~ by decreasing the deadline from the 5ms in the scheduler package to 1ms (then an even smaller slice of those parallel components can lead to a problem). It's also easier to verify this with a console open because the JavaScript will ececute slower (probably you can even use CPU throttling, but I didn't have time to verify this last thing).

@Andarist
Copy link
Contributor

I kept digging into this. I've failed to repro this in codesandbox when I've just tried to ensure that I'm yielding in the middle of "throwing siblings" but the render was able to complete just fine. So it turns out that Brian's hunch was right here - this is, at least partially, related to Next's ReactDevOverlay and I was able to repro this on codesandbox when using this component:
https://codesandbox.io/s/thirsty-elion-nefk9t?file=/src/App.js

So I think what happens here is that:

  • Next catches errors that are supposed to be handled by the custom ErrorBoundary created by Brian, roughly here
  • it emits an event, listens to it in the ReactDevOverlay (here), and updates state there
  • this in turn leads to an effect being flushed and yet another state update here

So based on that I think that the tree rerenders and the partially done work is being discarded and the cycle just continues. I'm not sure if this assessment is fully correct though because ReactDevOverlay's children are always the same (its parent doesn't rerender) and IIRC this should be optimized and shouldn't require a rerender. But perhaps since the work in children didn't yet commit this doesn't happen or something.

@bvaughn bvaughn changed the title Bug: Under certain Suspense scenarios, Error boundaries don't get triggered Bug: Potential infinite loop with Suspense (and Error boundaries not triggered) Jun 1, 2022
@sowrovsarkar63
Copy link

Does someone working on this issue ??

@bvaughn
Copy link
Contributor Author

bvaughn commented Jun 1, 2022

Does someone working on this issue ??

@sowrovsarkar63 No.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug Type: Bug
Projects
None yet
Development

No branches or pull requests

3 participants