Open raymondwang opened 1 month ago
hey @raymondwang . Can you please elaborate the issue and the expected result a bit more for the better understanding. That'll be really helpfull.
@Aryant01 The issue is that a Suspense rendered within another Suspense causes errant rerendering of the component within the first Suspense. The examples in the code sandboxes are more illustrative, but here's a brief example:
function Grandchild() {
return <p>Hello world!</p>
}
function Child() {
const LazyGrandchild = React.lazy(() => import('./Grandchild'));
return (
<Suspense>
<LazyGrandChild />
</Suspense>
);
}
function App() {
const LazyChild = React.lazy(() => import('./Child'));
return (
<Suspense>
<LazyChild />
</Suspense>
);
}
Here's what I'd expect to happen:
Instead, here's what's actually happening:
I think that what's happening under the hood in step 5 matches what's described here: https://react.dev/reference/react/Suspense#preventing-already-revealed-content-from-hiding — because Child sees a suspended component, its suspense is hoisted up to the closest parent suspense in App.
This issue can balloon far out of control very easily, as seen in this reproduction: https://codesandbox.io/p/sandbox/react-lazy-suspense-5g75x3
Instead of rerendering just once (which might be acceptable), this interaction can cause hundreds of errant rerenders.
I'm still working on a minimum reproduction but I think I'm seeing this. In my case this is also causing error 421 when hydrating after SSR. Removing either the inner lazy component, or just its parent boundary (but leaving the grandparent boundary in) still exhibits error 421.
Anyone else seeing the same or am I chasing a red herring?
This is a duplicate of https://github.com/facebook/react/issues/27573, which was closed without response. We're noticing this issue at scale, and it's fairly pronounced, with hundreds of rapid re-renders triggered by a single lazy component. I've forked the replication from original issue to demonstrate that this is still an issue in React 19:
https://codesandbox.io/p/sandbox/react-lazy-rerender-bug-forked-q4q6ym
The current behavior
The lazy parent component renders multiple times:
(In our environment, we've seen the number of re-renders proliferate to the hundreds. This matches the below reproduction.)
The expected behavior
The lazy parent component should only render one time.
The original issue had a reply that included a reproduction that matched the issue we're experiencing more closely: https://codesandbox.io/p/sandbox/react-lazy-suspense-5g75x3
Similar to what we're seeing, this repro has hundreds of re-renders, and the number is nondeterministic.
Our workaround for now is a lightweight replacement for
Suspense
using the Transition API to defer its lazy children, for usage in nested lazy contexts: