-
Notifications
You must be signed in to change notification settings - Fork 46.8k
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: Elements in ErrorBoundary are created twice, one of them becomes an orphan #26518
Comments
This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment! |
The issue is still reproducible in v19 canary. Stackblitz example here. |
When React is doing a concurrent render and something throws, it will re-render one more time synchronously in case the error was caused by inconsistent data stores. There is currently a bug where we're also doing that during a synchronous render which is wasteful. However, creating elements twice would be intended if the error happened during a concurrent render since we'd render twice. Host instance creation (e.g.
In which renderers would that be a problem? The reconciler docs call it out explicitly that host instance creation happens during render not commit and must be side-effect free: https://github.com/facebook/react/blob/main/packages/react-reconciler/README.md#createinstancetype-props-rootcontainer-hostcontext-internalhandle |
I noticed this in my custom renderer for Unity. Due to the nature of the platform, host instance creation had side-effects. I fixed it in my renderer after noticing this issue. But I can imagine this could happen in some Web Components if the author isn't aware of this maybe?
Thanks for this. I didn't know that. That particular line may not have existed in the docs back when I read it. Also this is the only case I am aware of, where a host instance is created and discarded without ever being mounted. So I was a bit surprised.
Just to clarify: The error doesn't happen inside the ErrorBoundary fallback. Is it still ok that the fallback is rendered twice, not only the component which throws the error? Or maybe I should say it like this. Maybe |
There are various cases where this could happen since React can render multiple times before actually committing. A concrete case would be inside a Suspense boundary. A component may finish rendering but then a sibling suspended. When the sibling resolves, the original render may have to be discarded.
We could investigate that but that wouldn't resolve the original issue, namely that host instance creation in your specific host has side-effects. |
As long as it is intended, it is not an issue for me. It is just a tiny bit wasteful in terms of performance, but not a big priority. |
React version: 18.2.0
Reproducible with 18.3.0-next-85de6fde5-20230328 as well.
As I observed, this is not an issue only in React-DOM. It happens with other renderers too. It can be an issue in the Reconciler or the main React package.
Issue does not seem to happen with React 17 based rendering (legacy mode?). You can test this by uncommenting the code at the end of the code example. However this can be simply because React 17 doesn't throw the error twice. In concurrent mode, error is thrown twice, so two ErrorBoundary are created. The stack traces for two errors look almost the same, except the latter error contains
recoverFromConcurrentError
in its call stack.Steps To Reproduce
Link to code example: Visit the CodeSandbox example and observe the logs.
In the code example, I mocked the
document.createElement
to see that it is called twice. However, one of the created elements aren't added to the DOM (becomes orphan).This may not be a big deal in HTML, but it can be a problem in other renderers where creating elements may have side effects. Also if the element has children, those children will also be created, potentially causing performance issues.
The current behavior
Native elements in ErrorBoundary are created twice, even though one of them are not added to the rendered tree.
The expected behavior
Elements should be created once.
The text was updated successfully, but these errors were encountered: