@samitouri / QOS-React-2 / commits / afb3d51dc6

Fix enableClientRenderFallbackOnTextMismatch flag (#26457)

With this flag off, we don't throw and therefore don't patch up the tree when suppression is off. Haven't tested. --------- Co-authored-by: Rick Hanlon <rickhanlonii@fb.com>

Sebastian Markbåge committed Mar 22, 2023 at 13:12 UTC afb3d51dc6310f0dbeffdd303eb3c6895e6f7db0
4 files changed +129 -5
packages/react-dom-bindings/src/client/ReactDOMComponent.js
+1 -1
@@ -1440,7 +1440,7 @@ export function diffHydratedProperties(
1440 shouldWarnDev,
1441 );
1442 }
1443 - if (!isConcurrentMode) {
1443 + if (!isConcurrentMode || !enableClientRenderFallbackOnTextMismatch) {
1444 updatePayload = ['children', children];
1445 }
1446 }
packages/react-dom/src/__tests__/ReactDOMFizzSuppressHydrationWarning-test.js
+120
@@ -130,6 +130,7 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
130 : children;
131 }
132
133 + // @gate enableClientRenderFallbackOnTextMismatch
134 it('suppresses but does not fix text mismatches with suppressHydrationWarning', async () => {
135 function App({isClient}) {
136 return (
@@ -169,6 +170,47 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
170 );
171 });
172
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
214 it('suppresses but does not fix multiple text node mismatches with suppressHydrationWarning', async () => {
215 function App({isClient}) {
216 return (
@@ -210,6 +252,48 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
252 );
253 });
254
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 +
297 it('errors on text-to-element mismatches with suppressHydrationWarning', async () => {
298 function App({isClient}) {
299 return (
@@ -261,6 +345,7 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
345 );
346 });
347
348 + // @gate enableClientRenderFallbackOnTextMismatch
349 it('suppresses but does not fix client-only single text node mismatches with suppressHydrationWarning', async () => {
350 function App({text}) {
351 return (
@@ -301,6 +386,41 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
386 );
387 });
388
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 +
424 // TODO: This behavior is not consistent with client-only single text node.
425
426 it('errors on server-only single text node mismatches with suppressHydrationWarning', async () => {
packages/react-dom/src/__tests__/ReactDOMFloat-test.js
+1 -1
@@ -5617,7 +5617,7 @@ background-color: green;
5617 ]);
5618 });
5619
5620 - // @gate enableFloat && enableHostSingletons && enableClientRenderFallbackOnTextMismatch
5620 + // @gate enableFloat && enableHostSingletons && (enableClientRenderFallbackOnTextMismatch || !__DEV__)
5621 it('can render a title before a singleton even if that singleton clears its contents', async () => {
5622 await actIntoEmptyDocument(() => {
5623 const {pipe} = renderToPipeableStream(
packages/react-reconciler/src/ReactFiberHydrationContext.js
+7 -3
@@ -35,7 +35,11 @@ import {
35 NoFlags,
36 DidCapture,
37 } from './ReactFiberFlags';
38 -import {enableHostSingletons, enableFloat} from 'shared/ReactFeatureFlags';
38 +import {
39 + enableHostSingletons,
40 + enableFloat,
41 + enableClientRenderFallbackOnTextMismatch,
42 +} from 'shared/ReactFeatureFlags';
43
44 import {
45 createFiberFromHostInstanceForDeletion,
@@ -728,7 +732,7 @@ function prepareToHydrateHostTextInstance(fiber: Fiber): boolean {
732 isConcurrentMode,
733 shouldWarnIfMismatchDev,
734 );
731 - if (isConcurrentMode) {
735 + if (isConcurrentMode && enableClientRenderFallbackOnTextMismatch) {
736 // In concurrent mode we never update the mismatched text,
737 // even if the error was ignored.
738 return false;
@@ -752,7 +756,7 @@ function prepareToHydrateHostTextInstance(fiber: Fiber): boolean {
756 isConcurrentMode,
757 shouldWarnIfMismatchDev,
758 );
755 - if (isConcurrentMode) {
759 + if (isConcurrentMode && enableClientRenderFallbackOnTextMismatch) {
760 // In concurrent mode we never update the mismatched text,
761 // even if the error was ignored.
762 return false;