1687
// takes into account both the priority of render and also whether showing a
1688
// fallback would produce a desirable user experience.
1689
1690
+ const handler = getSuspenseHandler();
1691
+ if (handler === null) {
1692
+ // There's no Suspense boundary that can provide a fallback. We have no
1693
+ // choice but to remain on the previous screen.
1694
+ // NOTE: We do this even for sync updates, for lack of any better option. In
1695
+ // the future, we may change how we handle this, like by putting the whole
1696
+ // root into a "detached" mode.
1697
+ return true;
1698
+ }
1699
+
1700
// TODO: Once `use` has fully replaced the `throw promise` pattern, we should
1701
// be able to remove the equivalent check in finishConcurrentRender, and rely
1702
// just on this one.
1715
}
1716
}
1717
1708
- const handler = getSuspenseHandler();
1709
- if (handler === null) {
1710
- // TODO: We should support suspending in the case where there's no
1711
- // parent Suspense boundary, even outside a transition. Somehow. Otherwise,
1712
- // an uncached promise can fall into an infinite loop.
1713
- } else {
1714
- if (
1715
- includesOnlyRetries(workInProgressRootRenderLanes) ||
1716
- // In this context, an OffscreenLane counts as a Retry
1717
- // TODO: It's become increasingly clear that Retries and Offscreen are
1718
- // deeply connected. They probably can be unified further.
1719
- includesSomeLane(workInProgressRootRenderLanes, OffscreenLane)
1720
- ) {
1721
- // During a retry, we can suspend rendering if the nearest Suspense boundary
1722
- // is the boundary of the "shell", because we're guaranteed not to block
1723
- // any new content from appearing.
1724
- //
1725
- // The reason we must check if this is a retry is because it guarantees
1726
- // that suspending the work loop won't block an actual update, because
1727
- // retries don't "update" anything; they fill in fallbacks that were left
1728
- // behind by a previous transition.
1729
- return handler === getShellBoundary();
1730
- }
1718
+ if (
1719
+ includesOnlyRetries(workInProgressRootRenderLanes) ||
1720
+ // In this context, an OffscreenLane counts as a Retry
1721
+ // TODO: It's become increasingly clear that Retries and Offscreen are
1722
+ // deeply connected. They probably can be unified further.
1723
+ includesSomeLane(workInProgressRootRenderLanes, OffscreenLane)
1724
+ ) {
1725
+ // During a retry, we can suspend rendering if the nearest Suspense boundary
1726
+ // is the boundary of the "shell", because we're guaranteed not to block
1727
+ // any new content from appearing.
1728
+ //
1729
+ // The reason we must check if this is a retry is because it guarantees
1730
+ // that suspending the work loop won't block an actual update, because
1731
+ // retries don't "update" anything; they fill in fallbacks that were left
1732
+ // behind by a previous transition.
1733
+ return handler === getShellBoundary();
1734
}
1735
1736
// For all other Lanes besides Transitions and Retries, we should not wait