Suspense / ErrorBoundary content rendered twice when hydrating with render
- [x] Check if updating to the latest Preact version resolves the issue
Describe the bug
We use ErrorBoundary and lazy from preact-iso for code-splitting our application but still being able to server-side render them in advance. With the upgrade to >10.19.0, we noticed that all our lazy components are rendered twice when first server-side rendered.
One important thing to note is that we use render instead of hydrate for hydrating our server-side rendered HTML because the server-side markup differs from what we render on the client. The bug does not appear when using hydrate. But changing that behaviour in our application would take an immense effort.
Switching from ErrorBoundary to Suspense did not solve the bug.
To Reproduce
- Go to https://codepen.io/phmitterer/pen/eYwYrpB
- Server-side rendering is simulated and "Hello, World!" is rendered
- After 1 second, client-side hydration kicks in and renders a second "Hello, World!"
Here is the same bug with Suspense instead of ErrorBoundary: https://codepen.io/phmitterer/pen/oNrNOVJ
Expected behavior
"Hello, World!" is only rendered once.
Hmm, this seems related to https://github.com/preactjs/preact/pull/4180 what seems to happen is that we opt out of resumed hydration due to leveraging render. When we initiate render we correctly re-use the initial components until we hit the lazy-boundary, it bubbles up the Promise to the error-boundary/suspense and then fails to recover the correct oldDom instead we are looking at either nothing or a disconnected node (the fallback) which is not dissimilar to what we've seen in other issues relating to Suspense.
I agree that we def should not duplicate the UI, I currently can't look at this but this can probably be reproduced in tests.