diff --git a/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js b/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js
index e16b2189b37f6..9d308c8e0acec 100644
--- a/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js
+++ b/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js
@@ -6131,4 +6131,55 @@ describe('ReactDOMFizzServer', () => {
// However, it does error the shell.
expect(fatalErrors).toEqual(['testing postpone']);
});
+
+ it(
+ 'a transition that flows into a dehydrated boundary should not suspend ' +
+ 'if the boundary is showing a fallback',
+ async () => {
+ let setSearch;
+ function App() {
+ const [search, _setSearch] = React.useState('initial query');
+ setSearch = _setSearch;
+ return (
+
+ );
+ }
+
+ // Render the initial HTML, which is showing a fallback.
+ await act(() => {
+ const {pipe} = renderToPipeableStream();
+ pipe(writable);
+ });
+
+ // Start hydrating.
+ await clientAct(() => {
+ ReactDOMClient.hydrateRoot(container, );
+ });
+ expect(getVisibleChildren(container)).toEqual(
+
+
initial query
+
Loading...
+
,
+ );
+
+ // Before the HTML has streamed in, update the query. The part outside
+ // the fallback should be allowed to finish.
+ await clientAct(() => {
+ React.startTransition(() => setSearch('updated query'));
+ });
+ expect(getVisibleChildren(container)).toEqual(
+
+
updated query
+
Loading...
+
,
+ );
+ },
+ );
});
diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.js b/packages/react-reconciler/src/ReactFiberBeginWork.js
index 57a86e6984d80..abb4d54373560 100644
--- a/packages/react-reconciler/src/ReactFiberBeginWork.js
+++ b/packages/react-reconciler/src/ReactFiberBeginWork.js
@@ -2958,7 +2958,15 @@ function updateDehydratedSuspenseComponent(
// TODO: We should ideally have a sync hydration lane that we can apply to do
// a pass where we hydrate this subtree in place using the previous Context and then
// reapply the update afterwards.
- renderDidSuspendDelayIfPossible();
+ if (isSuspenseInstancePending(suspenseInstance)) {
+ // This is a dehydrated suspense instance. We don't need to suspend
+ // because we're already showing a fallback.
+ // TODO: The Fizz runtime might still stream in completed HTML, out-of-
+ // band. Should we fix this? There's a version of this bug that happens
+ // during client rendering, too. Needs more consideration.
+ } else {
+ renderDidSuspendDelayIfPossible();
+ }
return retrySuspenseComponentWithoutHydrating(
current,
workInProgress,