Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
<div>
<div>{search}</div>
<div>
<Suspense fallback="Loading...">
<AsyncText text="Async" />
</Suspense>
</div>
</div>
);
}

// Render the initial HTML, which is showing a fallback.
await act(() => {
const {pipe} = renderToPipeableStream(<App />);
pipe(writable);
});

// Start hydrating.
await clientAct(() => {
ReactDOMClient.hydrateRoot(container, <App />);
});
expect(getVisibleChildren(container)).toEqual(
<div>
<div>initial query</div>
<div>Loading...</div>
</div>,
);

// 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(
<div>
<div>updated query</div>
<div>Loading...</div>
</div>,
);
},
);
});
10 changes: 9 additions & 1 deletion packages/react-reconciler/src/ReactFiberBeginWork.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down