Skip to content

Commit

Permalink
Remove enableClientRenderFallbackOnTextMismatch flag
Browse files Browse the repository at this point in the history
  • Loading branch information
sebmarkbage committed Mar 1, 2024
1 parent ea46e91 commit 459fca3
Show file tree
Hide file tree
Showing 19 changed files with 71 additions and 295 deletions.
19 changes: 3 additions & 16 deletions packages/react-dom-bindings/src/client/ReactDOMComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ import sanitizeURL from '../shared/sanitizeURL';
import {
enableBigIntSupport,
enableCustomElementPropertySupport,
enableClientRenderFallbackOnTextMismatch,
enableFormActions,
disableIEWorkarounds,
enableTrustedTypesIntegration,
Expand Down Expand Up @@ -349,11 +348,9 @@ export function checkForUnmatchedText(
}
}

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

function noop() {}
Expand Down Expand Up @@ -2835,16 +2832,6 @@ export function diffHydratedProperties(
if (props.suppressHydrationWarning !== true) {
checkForUnmatchedText(domElement.textContent, children, shouldWarnDev);
}
if (!enableClientRenderFallbackOnTextMismatch) {
// We really should be patching this in the commit phase but since
// this only affects legacy mode hydration which is deprecated anyway
// we can get away with it.
// Host singletons get their children appended and don't use the text
// content mechanism.
if (tag !== 'body') {
domElement.textContent = (children: any);
}
}
}
}

Expand Down
6 changes: 1 addition & 5 deletions packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4415,7 +4415,6 @@ describe('ReactDOMFizzServer', () => {
);
});

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

// @gate enableClientRenderFallbackOnTextMismatch
it('only warns once on hydration mismatch while within a suspense boundary', async () => {
const originalConsoleError = console.error;
const mockError = jest.fn();
Expand Down Expand Up @@ -5776,9 +5774,7 @@ describe('ReactDOMFizzServer', () => {
} else {
expect(errors).toEqual(
[
gate(flags => flags.enableClientRenderFallbackOnTextMismatch)
? 'Text content does not match server-rendered HTML.'
: null,
'Text content does not match server-rendered HTML.',
'Hydration failed because the initial UI does not match what was rendered on the server.',
'There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.',
].filter(Boolean),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,6 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
: children;
}

// @gate enableClientRenderFallbackOnTextMismatch
it('suppresses but does not fix text mismatches with suppressHydrationWarning', async () => {
function App({isClient}) {
return (
Expand Down Expand Up @@ -170,47 +169,6 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
);
});

// @gate !enableClientRenderFallbackOnTextMismatch
it('suppresses and fixes text mismatches with suppressHydrationWarning', async () => {
function App({isClient}) {
return (
<div>
<span suppressHydrationWarning={true}>
{isClient ? 'Client Text' : 'Server Text'}
</span>
<span suppressHydrationWarning={true}>{isClient ? 2 : 1}</span>
</div>
);
}
await act(() => {
const {pipe} = ReactDOMFizzServer.renderToPipeableStream(
<App isClient={false} />,
);
pipe(writable);
});
expect(getVisibleChildren(container)).toEqual(
<div>
<span>Server Text</span>
<span>1</span>
</div>,
);
ReactDOMClient.hydrateRoot(container, <App isClient={true} />, {
onRecoverableError(error) {
// Don't miss a hydration error. There should be none.
Scheduler.log(error.message);
},
});
await waitForAll([]);
// The text mismatch should be *silently* fixed. Even in production.
expect(getVisibleChildren(container)).toEqual(
<div>
<span>Client Text</span>
<span>2</span>
</div>,
);
});

// @gate enableClientRenderFallbackOnTextMismatch
it('suppresses but does not fix multiple text node mismatches with suppressHydrationWarning', async () => {
function App({isClient}) {
return (
Expand Down Expand Up @@ -252,48 +210,6 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
);
});

// @gate !enableClientRenderFallbackOnTextMismatch
it('suppresses and fixes multiple text node mismatches with suppressHydrationWarning', async () => {
function App({isClient}) {
return (
<div>
<span suppressHydrationWarning={true}>
{isClient ? 'Client1' : 'Server1'}
{isClient ? 'Client2' : 'Server2'}
</span>
</div>
);
}
await act(() => {
const {pipe} = ReactDOMFizzServer.renderToPipeableStream(
<App isClient={false} />,
);
pipe(writable);
});
expect(getVisibleChildren(container)).toEqual(
<div>
<span>
{'Server1'}
{'Server2'}
</span>
</div>,
);
ReactDOMClient.hydrateRoot(container, <App isClient={true} />, {
onRecoverableError(error) {
Scheduler.log(error.message);
},
});
await waitForAll([]);
expect(getVisibleChildren(container)).toEqual(
<div>
<span>
{'Client1'}
{'Client2'}
</span>
</div>,
);
});

it('errors on text-to-element mismatches with suppressHydrationWarning', async () => {
function App({isClient}) {
return (
Expand Down Expand Up @@ -345,7 +261,6 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
);
});

// @gate enableClientRenderFallbackOnTextMismatch
it('suppresses but does not fix client-only single text node mismatches with suppressHydrationWarning', async () => {
function App({text}) {
return (
Expand Down Expand Up @@ -386,41 +301,6 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
);
});

// @gate !enableClientRenderFallbackOnTextMismatch
it('suppresses and fixes client-only single text node mismatches with suppressHydrationWarning', async () => {
function App({isClient}) {
return (
<div>
<span suppressHydrationWarning={true}>
{isClient ? 'Client' : null}
</span>
</div>
);
}
await act(() => {
const {pipe} = ReactDOMFizzServer.renderToPipeableStream(
<App isClient={false} />,
);
pipe(writable);
});
expect(getVisibleChildren(container)).toEqual(
<div>
<span />
</div>,
);
ReactDOMClient.hydrateRoot(container, <App isClient={true} />, {
onRecoverableError(error) {
Scheduler.log(error.message);
},
});
await waitForAll([]);
expect(getVisibleChildren(container)).toEqual(
<div>
<span>{'Client'}</span>
</div>,
);
});

// TODO: This behavior is not consistent with client-only single text node.

it('errors on server-only single text node mismatches with suppressHydrationWarning', async () => {
Expand Down
4 changes: 2 additions & 2 deletions packages/react-dom/src/__tests__/ReactDOMFloat-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6423,7 +6423,7 @@ body {
);
});

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

// @gate enableFloat && (enableClientRenderFallbackOnTextMismatch || !__DEV__)
// @gate enableFloat
it('can render a title before a singleton even if that singleton clears its contents', async () => {
await act(() => {
const {pipe} = renderToPipeableStream(
Expand Down
93 changes: 31 additions & 62 deletions packages/react-dom/src/__tests__/ReactDOMHydrationDiff-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,28 +89,17 @@ describe('ReactDOMServerHydration', () => {
</div>
);
}
if (gate(flags => flags.enableClientRenderFallbackOnTextMismatch)) {
expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`
[
"Warning: Text content did not match. Server: "server" Client: "client"
in main (at **)
in div (at **)
in Mismatch (at **)",
"Warning: An error occurred during hydration. The server HTML was replaced with client content in <div>.",
"Caught [Text content does not match server-rendered HTML.]",
"Caught [There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.]",
]
`);
} else {
expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`
[
"Warning: Text content did not match. Server: "server" Client: "client"
in main (at **)
in div (at **)
in Mismatch (at **)",
]
`);
}
expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`
[
"Warning: Text content did not match. Server: "server" Client: "client"
in main (at **)
in div (at **)
in Mismatch (at **)",
"Warning: An error occurred during hydration. The server HTML was replaced with client content in <div>.",
"Caught [Text content does not match server-rendered HTML.]",
"Caught [There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.]",
]
`);
});

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

/* eslint-disable no-irregular-whitespace */
if (gate(flags => flags.enableClientRenderFallbackOnTextMismatch)) {
expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`
[
"Warning: Text content did not match. Server: "This markup contains an nbsp entity:   server text" Client: "This markup contains an nbsp entity:   client text"
in div (at **)
in Mismatch (at **)",
"Warning: An error occurred during hydration. The server HTML was replaced with client content in <div>.",
"Caught [Text content does not match server-rendered HTML.]",
"Caught [There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.]",
]
`);
} else {
expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`
[
"Warning: Text content did not match. Server: "This markup contains an nbsp entity:   server text" Client: "This markup contains an nbsp entity:   client text"
in div (at **)
in Mismatch (at **)",
]
`);
}
expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`
[
"Warning: Text content did not match. Server: "This markup contains an nbsp entity:   server text" Client: "This markup contains an nbsp entity:   client text"
in div (at **)
in Mismatch (at **)",
"Warning: An error occurred during hydration. The server HTML was replaced with client content in <div>.",
"Caught [Text content does not match server-rendered HTML.]",
"Caught [There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.]",
]
`);
/* eslint-enable no-irregular-whitespace */
});

Expand Down Expand Up @@ -397,26 +376,16 @@ describe('ReactDOMServerHydration', () => {
function Mismatch({isClient}) {
return <div className="parent">{isClient && 'only'}</div>;
}
if (gate(flags => flags.enableClientRenderFallbackOnTextMismatch)) {
expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`
[
"Warning: Text content did not match. Server: "" Client: "only"
in div (at **)
in Mismatch (at **)",
"Warning: An error occurred during hydration. The server HTML was replaced with client content in <div>.",
"Caught [Text content does not match server-rendered HTML.]",
"Caught [There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.]",
]
`);
} else {
expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`
[
"Warning: Text content did not match. Server: "" Client: "only"
in div (at **)
in Mismatch (at **)",
]
`);
}
expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`
[
"Warning: Text content did not match. Server: "" Client: "only"
in div (at **)
in Mismatch (at **)",
"Warning: An error occurred during hydration. The server HTML was replaced with client content in <div>.",
"Caught [Text content does not match server-rendered HTML.]",
"Caught [There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.]",
]
`);
});

// @gate __DEV__
Expand Down
Loading

0 comments on commit 459fca3

Please sign in to comment.