Skip to content

Commit c7917fe

Browse files
authored
Test showing that a mismatch at the root recovers with client render but shows loading state (#22873)
* rm console.log * gate test * move test * show fallback state
1 parent 12bffc7 commit c7917fe

File tree

1 file changed

+63
-0
lines changed

1 file changed

+63
-0
lines changed

packages/react-dom/src/__tests__/ReactDOMServerPartialHydration-test.internal.js

+63
Original file line numberDiff line numberDiff line change
@@ -3014,4 +3014,67 @@ describe('ReactDOMServerPartialHydration', () => {
30143014
);
30153015

30163016
itHydratesWithoutMismatch('an empty string in class component', TestAppClass);
3017+
3018+
// @gate enableClientRenderFallbackOnHydrationMismatch
3019+
it('fallback to client render on hydration mismatch at root', async () => {
3020+
let isClient = false;
3021+
let suspend = true;
3022+
let resolve;
3023+
const promise = new Promise((res, rej) => {
3024+
resolve = () => {
3025+
suspend = false;
3026+
res();
3027+
};
3028+
});
3029+
function App() {
3030+
return (
3031+
<>
3032+
<Suspense fallback={<div>Loading</div>}>
3033+
<ChildThatSuspends id={1} />
3034+
</Suspense>
3035+
{isClient ? <span>client</span> : <div>server</div>}
3036+
<Suspense fallback={<div>Loading</div>}>
3037+
<ChildThatSuspends id={2} />
3038+
</Suspense>
3039+
</>
3040+
);
3041+
}
3042+
function ChildThatSuspends({id}) {
3043+
if (isClient && suspend) {
3044+
throw promise;
3045+
}
3046+
return <div>{id}</div>;
3047+
}
3048+
3049+
const finalHTML = ReactDOMServer.renderToString(<App />);
3050+
3051+
const container = document.createElement('div');
3052+
document.body.appendChild(container);
3053+
container.innerHTML = finalHTML;
3054+
isClient = true;
3055+
3056+
expect(() => {
3057+
act(() => {
3058+
ReactDOM.hydrateRoot(container, <App />);
3059+
});
3060+
}).toErrorDev(
3061+
'Warning: An error occurred during hydration. ' +
3062+
'The server HTML was replaced with client content in <div>.',
3063+
{withoutStack: true},
3064+
);
3065+
3066+
// We show fallback state when mismatch happens at root
3067+
expect(container.innerHTML).toEqual(
3068+
'<div>Loading</div><span>client</span><div>Loading</div>',
3069+
);
3070+
3071+
await act(async () => {
3072+
resolve();
3073+
await promise;
3074+
});
3075+
3076+
expect(container.innerHTML).toEqual(
3077+
'<div>1</div><span>client</span><div>2</div>',
3078+
);
3079+
});
30173080
});

0 commit comments

Comments
 (0)