Fix suppressHydrationWarning not working in production (#24271)
This commit is contained in:
parent
985272e268
commit
fc47cb1b61
|
@ -2811,4 +2811,96 @@ describe('ReactDOMFizzServer', () => {
|
|||
</ul>,
|
||||
);
|
||||
});
|
||||
|
||||
// @gate experimental
|
||||
it('suppresses and fixes text mismatches with suppressHydrationWarning', async () => {
|
||||
function App({isClient}) {
|
||||
return (
|
||||
<div>
|
||||
<span
|
||||
suppressHydrationWarning={true}
|
||||
data-attr={isClient ? 'client-attr' : 'server-attr'}>
|
||||
{isClient ? 'Client Text' : 'Server Text'}
|
||||
</span>
|
||||
<span suppressHydrationWarning={true}>{isClient ? 2 : 1}</span>
|
||||
<span suppressHydrationWarning={true}>
|
||||
hello,{isClient ? 'client' : 'server'}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
await act(async () => {
|
||||
const {pipe} = ReactDOMFizzServer.renderToPipeableStream(
|
||||
<App isClient={false} />,
|
||||
);
|
||||
pipe(writable);
|
||||
});
|
||||
expect(getVisibleChildren(container)).toEqual(
|
||||
<div>
|
||||
<span data-attr="server-attr">Server Text</span>
|
||||
<span>1</span>
|
||||
<span>
|
||||
{'hello,'}
|
||||
{'server'}
|
||||
</span>
|
||||
</div>,
|
||||
);
|
||||
ReactDOMClient.hydrateRoot(container, <App isClient={true} />, {
|
||||
onRecoverableError(error) {
|
||||
// Don't miss a hydration error. There should be none.
|
||||
Scheduler.unstable_yieldValue(error.message);
|
||||
},
|
||||
});
|
||||
expect(Scheduler).toFlushAndYield([]);
|
||||
// The text mismatch should be *silently* fixed. Even in production.
|
||||
// The attribute mismatch should be ignored and not fixed.
|
||||
expect(getVisibleChildren(container)).toEqual(
|
||||
<div>
|
||||
<span data-attr="server-attr">Client Text</span>
|
||||
<span>2</span>
|
||||
<span>
|
||||
{'hello,'}
|
||||
{'client'}
|
||||
</span>
|
||||
</div>,
|
||||
);
|
||||
});
|
||||
|
||||
// @gate experimental
|
||||
it('suppresses and does not fix html mismatches with suppressHydrationWarning', async () => {
|
||||
function App({isClient}) {
|
||||
return (
|
||||
<div>
|
||||
<p
|
||||
suppressHydrationWarning={true}
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: isClient ? 'Client HTML' : 'Server HTML',
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
await act(async () => {
|
||||
const {pipe} = ReactDOMFizzServer.renderToPipeableStream(
|
||||
<App isClient={false} />,
|
||||
);
|
||||
pipe(writable);
|
||||
});
|
||||
expect(getVisibleChildren(container)).toEqual(
|
||||
<div>
|
||||
<p>Server HTML</p>
|
||||
</div>,
|
||||
);
|
||||
ReactDOMClient.hydrateRoot(container, <App isClient={true} />, {
|
||||
onRecoverableError(error) {
|
||||
Scheduler.unstable_yieldValue(error.message);
|
||||
},
|
||||
});
|
||||
expect(Scheduler).toFlushAndYield([]);
|
||||
expect(getVisibleChildren(container)).toEqual(
|
||||
<div>
|
||||
<p>Server HTML</p>
|
||||
</div>,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -91,7 +91,6 @@ const STYLE = 'style';
|
|||
const HTML = '__html';
|
||||
|
||||
let warnedUnknownTags;
|
||||
let suppressHydrationWarning;
|
||||
|
||||
let validatePropertiesInDevelopment;
|
||||
let warnForPropDifference;
|
||||
|
@ -875,7 +874,6 @@ export function diffHydratedProperties(
|
|||
let extraAttributeNames: Set<string>;
|
||||
|
||||
if (__DEV__) {
|
||||
suppressHydrationWarning = rawProps[SUPPRESS_HYDRATION_WARNING] === true;
|
||||
isCustomComponentTag = isCustomComponent(tag, rawProps);
|
||||
validatePropertiesInDevelopment(tag, rawProps);
|
||||
}
|
||||
|
@ -984,7 +982,7 @@ export function diffHydratedProperties(
|
|||
// TODO: Should we use domElement.firstChild.nodeValue to compare?
|
||||
if (typeof nextProp === 'string') {
|
||||
if (domElement.textContent !== nextProp) {
|
||||
if (!suppressHydrationWarning) {
|
||||
if (rawProps[SUPPRESS_HYDRATION_WARNING] !== true) {
|
||||
checkForUnmatchedText(
|
||||
domElement.textContent,
|
||||
nextProp,
|
||||
|
@ -996,7 +994,7 @@ export function diffHydratedProperties(
|
|||
}
|
||||
} else if (typeof nextProp === 'number') {
|
||||
if (domElement.textContent !== '' + nextProp) {
|
||||
if (!suppressHydrationWarning) {
|
||||
if (rawProps[SUPPRESS_HYDRATION_WARNING] !== true) {
|
||||
checkForUnmatchedText(
|
||||
domElement.textContent,
|
||||
nextProp,
|
||||
|
@ -1028,7 +1026,7 @@ export function diffHydratedProperties(
|
|||
isCustomComponentTag && enableCustomElementPropertySupport
|
||||
? null
|
||||
: getPropertyInfo(propKey);
|
||||
if (suppressHydrationWarning) {
|
||||
if (rawProps[SUPPRESS_HYDRATION_WARNING] === true) {
|
||||
// Don't bother comparing. We're ignoring all these warnings.
|
||||
} else if (
|
||||
propKey === SUPPRESS_CONTENT_EDITABLE_WARNING ||
|
||||
|
@ -1150,8 +1148,11 @@ export function diffHydratedProperties(
|
|||
|
||||
if (__DEV__) {
|
||||
if (shouldWarnDev) {
|
||||
// $FlowFixMe - Should be inferred as not undefined.
|
||||
if (extraAttributeNames.size > 0 && !suppressHydrationWarning) {
|
||||
if (
|
||||
// $FlowFixMe - Should be inferred as not undefined.
|
||||
extraAttributeNames.size > 0 &&
|
||||
rawProps[SUPPRESS_HYDRATION_WARNING] !== true
|
||||
) {
|
||||
// $FlowFixMe - Should be inferred as not undefined.
|
||||
warnForExtraAttributes(extraAttributeNames);
|
||||
}
|
||||
|
|
|
@ -132,10 +132,7 @@ type SelectionInformation = {|
|
|||
selectionRange: mixed,
|
||||
|};
|
||||
|
||||
let SUPPRESS_HYDRATION_WARNING;
|
||||
if (__DEV__) {
|
||||
SUPPRESS_HYDRATION_WARNING = 'suppressHydrationWarning';
|
||||
}
|
||||
const SUPPRESS_HYDRATION_WARNING = 'suppressHydrationWarning';
|
||||
|
||||
const SUSPENSE_START_DATA = '$';
|
||||
const SUSPENSE_END_DATA = '/$';
|
||||
|
|
Loading…
Reference in New Issue