Skip to content

Commit 4eeb8c2

Browse files
committed
Remove enableClientRenderFallbackOnTextMismatch flag
1 parent e6eb98d commit 4eeb8c2

19 files changed

+71
-295
lines changed

packages/react-dom-bindings/src/client/ReactDOMComponent.js

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ import sanitizeURL from '../shared/sanitizeURL';
6868
import {
6969
enableBigIntSupport,
7070
enableCustomElementPropertySupport,
71-
enableClientRenderFallbackOnTextMismatch,
7271
enableFormActions,
7372
disableIEWorkarounds,
7473
enableTrustedTypesIntegration,
@@ -349,11 +348,9 @@ export function checkForUnmatchedText(
349348
}
350349
}
351350

352-
if (enableClientRenderFallbackOnTextMismatch) {
353-
// In concurrent roots, we throw when there's a text mismatch and revert to
354-
// client rendering, up to the nearest Suspense boundary.
355-
throw new Error('Text content does not match server-rendered HTML.');
356-
}
351+
// In concurrent roots, we throw when there's a text mismatch and revert to
352+
// client rendering, up to the nearest Suspense boundary.
353+
throw new Error('Text content does not match server-rendered HTML.');
357354
}
358355

359356
function noop() {}
@@ -2835,16 +2832,6 @@ export function diffHydratedProperties(
28352832
if (props.suppressHydrationWarning !== true) {
28362833
checkForUnmatchedText(domElement.textContent, children, shouldWarnDev);
28372834
}
2838-
if (!enableClientRenderFallbackOnTextMismatch) {
2839-
// We really should be patching this in the commit phase but since
2840-
// this only affects legacy mode hydration which is deprecated anyway
2841-
// we can get away with it.
2842-
// Host singletons get their children appended and don't use the text
2843-
// content mechanism.
2844-
if (tag !== 'body') {
2845-
domElement.textContent = (children: any);
2846-
}
2847-
}
28482835
}
28492836
}
28502837

packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4415,7 +4415,6 @@ describe('ReactDOMFizzServer', () => {
44154415
);
44164416
});
44174417

4418-
// @gate enableClientRenderFallbackOnTextMismatch
44194418
it('#24384: Suspending should halt hydration warnings but still emit hydration warnings after unsuspending if mismatches are genuine', async () => {
44204419
const makeApp = () => {
44214420
let resolve, resolved;
@@ -4501,7 +4500,6 @@ describe('ReactDOMFizzServer', () => {
45014500
await waitForAll([]);
45024501
});
45034502

4504-
// @gate enableClientRenderFallbackOnTextMismatch
45054503
it('only warns once on hydration mismatch while within a suspense boundary', async () => {
45064504
const originalConsoleError = console.error;
45074505
const mockError = jest.fn();
@@ -5776,9 +5774,7 @@ describe('ReactDOMFizzServer', () => {
57765774
} else {
57775775
expect(errors).toEqual(
57785776
[
5779-
gate(flags => flags.enableClientRenderFallbackOnTextMismatch)
5780-
? 'Text content does not match server-rendered HTML.'
5781-
: null,
5777+
'Text content does not match server-rendered HTML.',
57825778
'Hydration failed because the initial UI does not match what was rendered on the server.',
57835779
'There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.',
57845780
].filter(Boolean),

packages/react-dom/src/__tests__/ReactDOMFizzSuppressHydrationWarning-test.js

Lines changed: 0 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,6 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
130130
: children;
131131
}
132132

133-
// @gate enableClientRenderFallbackOnTextMismatch
134133
it('suppresses but does not fix text mismatches with suppressHydrationWarning', async () => {
135134
function App({isClient}) {
136135
return (
@@ -170,47 +169,6 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
170169
);
171170
});
172171

173-
// @gate !enableClientRenderFallbackOnTextMismatch
174-
it('suppresses and fixes text mismatches with suppressHydrationWarning', async () => {
175-
function App({isClient}) {
176-
return (
177-
<div>
178-
<span suppressHydrationWarning={true}>
179-
{isClient ? 'Client Text' : 'Server Text'}
180-
</span>
181-
<span suppressHydrationWarning={true}>{isClient ? 2 : 1}</span>
182-
</div>
183-
);
184-
}
185-
await act(() => {
186-
const {pipe} = ReactDOMFizzServer.renderToPipeableStream(
187-
<App isClient={false} />,
188-
);
189-
pipe(writable);
190-
});
191-
expect(getVisibleChildren(container)).toEqual(
192-
<div>
193-
<span>Server Text</span>
194-
<span>1</span>
195-
</div>,
196-
);
197-
ReactDOMClient.hydrateRoot(container, <App isClient={true} />, {
198-
onRecoverableError(error) {
199-
// Don't miss a hydration error. There should be none.
200-
Scheduler.log(error.message);
201-
},
202-
});
203-
await waitForAll([]);
204-
// The text mismatch should be *silently* fixed. Even in production.
205-
expect(getVisibleChildren(container)).toEqual(
206-
<div>
207-
<span>Client Text</span>
208-
<span>2</span>
209-
</div>,
210-
);
211-
});
212-
213-
// @gate enableClientRenderFallbackOnTextMismatch
214172
it('suppresses but does not fix multiple text node mismatches with suppressHydrationWarning', async () => {
215173
function App({isClient}) {
216174
return (
@@ -252,48 +210,6 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
252210
);
253211
});
254212

255-
// @gate !enableClientRenderFallbackOnTextMismatch
256-
it('suppresses and fixes multiple text node mismatches with suppressHydrationWarning', async () => {
257-
function App({isClient}) {
258-
return (
259-
<div>
260-
<span suppressHydrationWarning={true}>
261-
{isClient ? 'Client1' : 'Server1'}
262-
{isClient ? 'Client2' : 'Server2'}
263-
</span>
264-
</div>
265-
);
266-
}
267-
await act(() => {
268-
const {pipe} = ReactDOMFizzServer.renderToPipeableStream(
269-
<App isClient={false} />,
270-
);
271-
pipe(writable);
272-
});
273-
expect(getVisibleChildren(container)).toEqual(
274-
<div>
275-
<span>
276-
{'Server1'}
277-
{'Server2'}
278-
</span>
279-
</div>,
280-
);
281-
ReactDOMClient.hydrateRoot(container, <App isClient={true} />, {
282-
onRecoverableError(error) {
283-
Scheduler.log(error.message);
284-
},
285-
});
286-
await waitForAll([]);
287-
expect(getVisibleChildren(container)).toEqual(
288-
<div>
289-
<span>
290-
{'Client1'}
291-
{'Client2'}
292-
</span>
293-
</div>,
294-
);
295-
});
296-
297213
it('errors on text-to-element mismatches with suppressHydrationWarning', async () => {
298214
function App({isClient}) {
299215
return (
@@ -345,7 +261,6 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
345261
);
346262
});
347263

348-
// @gate enableClientRenderFallbackOnTextMismatch
349264
it('suppresses but does not fix client-only single text node mismatches with suppressHydrationWarning', async () => {
350265
function App({text}) {
351266
return (
@@ -386,41 +301,6 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
386301
);
387302
});
388303

389-
// @gate !enableClientRenderFallbackOnTextMismatch
390-
it('suppresses and fixes client-only single text node mismatches with suppressHydrationWarning', async () => {
391-
function App({isClient}) {
392-
return (
393-
<div>
394-
<span suppressHydrationWarning={true}>
395-
{isClient ? 'Client' : null}
396-
</span>
397-
</div>
398-
);
399-
}
400-
await act(() => {
401-
const {pipe} = ReactDOMFizzServer.renderToPipeableStream(
402-
<App isClient={false} />,
403-
);
404-
pipe(writable);
405-
});
406-
expect(getVisibleChildren(container)).toEqual(
407-
<div>
408-
<span />
409-
</div>,
410-
);
411-
ReactDOMClient.hydrateRoot(container, <App isClient={true} />, {
412-
onRecoverableError(error) {
413-
Scheduler.log(error.message);
414-
},
415-
});
416-
await waitForAll([]);
417-
expect(getVisibleChildren(container)).toEqual(
418-
<div>
419-
<span>{'Client'}</span>
420-
</div>,
421-
);
422-
});
423-
424304
// TODO: This behavior is not consistent with client-only single text node.
425305

426306
it('errors on server-only single text node mismatches with suppressHydrationWarning', async () => {

packages/react-dom/src/__tests__/ReactDOMFloat-test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6423,7 +6423,7 @@ body {
64236423
);
64246424
});
64256425

6426-
// @gate enableFloat && enableClientRenderFallbackOnTextMismatch
6426+
// @gate enableFloat
64276427
it('retains styles even when a new html, head, and/body mount', async () => {
64286428
await act(() => {
64296429
const {pipe} = renderToPipeableStream(
@@ -8234,7 +8234,7 @@ background-color: green;
82348234
]);
82358235
});
82368236

8237-
// @gate enableFloat && (enableClientRenderFallbackOnTextMismatch || !__DEV__)
8237+
// @gate enableFloat
82388238
it('can render a title before a singleton even if that singleton clears its contents', async () => {
82398239
await act(() => {
82408240
const {pipe} = renderToPipeableStream(

packages/react-dom/src/__tests__/ReactDOMHydrationDiff-test.js

Lines changed: 31 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -89,28 +89,17 @@ describe('ReactDOMServerHydration', () => {
8989
</div>
9090
);
9191
}
92-
if (gate(flags => flags.enableClientRenderFallbackOnTextMismatch)) {
93-
expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`
94-
[
95-
"Warning: Text content did not match. Server: "server" Client: "client"
96-
in main (at **)
97-
in div (at **)
98-
in Mismatch (at **)",
99-
"Warning: An error occurred during hydration. The server HTML was replaced with client content in <div>.",
100-
"Caught [Text content does not match server-rendered HTML.]",
101-
"Caught [There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.]",
102-
]
103-
`);
104-
} else {
105-
expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`
106-
[
107-
"Warning: Text content did not match. Server: "server" Client: "client"
108-
in main (at **)
109-
in div (at **)
110-
in Mismatch (at **)",
111-
]
112-
`);
113-
}
92+
expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`
93+
[
94+
"Warning: Text content did not match. Server: "server" Client: "client"
95+
in main (at **)
96+
in div (at **)
97+
in Mismatch (at **)",
98+
"Warning: An error occurred during hydration. The server HTML was replaced with client content in <div>.",
99+
"Caught [Text content does not match server-rendered HTML.]",
100+
"Caught [There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.]",
101+
]
102+
`);
114103
});
115104

116105
// @gate __DEV__
@@ -127,26 +116,16 @@ describe('ReactDOMServerHydration', () => {
127116
}
128117

129118
/* eslint-disable no-irregular-whitespace */
130-
if (gate(flags => flags.enableClientRenderFallbackOnTextMismatch)) {
131-
expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`
132-
[
133-
"Warning: Text content did not match. Server: "This markup contains an nbsp entity:   server text" Client: "This markup contains an nbsp entity:   client text"
134-
in div (at **)
135-
in Mismatch (at **)",
136-
"Warning: An error occurred during hydration. The server HTML was replaced with client content in <div>.",
137-
"Caught [Text content does not match server-rendered HTML.]",
138-
"Caught [There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.]",
139-
]
140-
`);
141-
} else {
142-
expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`
143-
[
144-
"Warning: Text content did not match. Server: "This markup contains an nbsp entity:   server text" Client: "This markup contains an nbsp entity:   client text"
145-
in div (at **)
146-
in Mismatch (at **)",
147-
]
148-
`);
149-
}
119+
expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`
120+
[
121+
"Warning: Text content did not match. Server: "This markup contains an nbsp entity:   server text" Client: "This markup contains an nbsp entity:   client text"
122+
in div (at **)
123+
in Mismatch (at **)",
124+
"Warning: An error occurred during hydration. The server HTML was replaced with client content in <div>.",
125+
"Caught [Text content does not match server-rendered HTML.]",
126+
"Caught [There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.]",
127+
]
128+
`);
150129
/* eslint-enable no-irregular-whitespace */
151130
});
152131

@@ -397,26 +376,16 @@ describe('ReactDOMServerHydration', () => {
397376
function Mismatch({isClient}) {
398377
return <div className="parent">{isClient && 'only'}</div>;
399378
}
400-
if (gate(flags => flags.enableClientRenderFallbackOnTextMismatch)) {
401-
expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`
402-
[
403-
"Warning: Text content did not match. Server: "" Client: "only"
404-
in div (at **)
405-
in Mismatch (at **)",
406-
"Warning: An error occurred during hydration. The server HTML was replaced with client content in <div>.",
407-
"Caught [Text content does not match server-rendered HTML.]",
408-
"Caught [There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.]",
409-
]
410-
`);
411-
} else {
412-
expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`
413-
[
414-
"Warning: Text content did not match. Server: "" Client: "only"
415-
in div (at **)
416-
in Mismatch (at **)",
417-
]
418-
`);
419-
}
379+
expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`
380+
[
381+
"Warning: Text content did not match. Server: "" Client: "only"
382+
in div (at **)
383+
in Mismatch (at **)",
384+
"Warning: An error occurred during hydration. The server HTML was replaced with client content in <div>.",
385+
"Caught [Text content does not match server-rendered HTML.]",
386+
"Caught [There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.]",
387+
]
388+
`);
420389
});
421390

422391
// @gate __DEV__

0 commit comments

Comments
 (0)