Don't mute hydration errors forcing client render (#24276)

* Don't mute hydration errors forcing client render

* Nits
This commit is contained in:
dan
2022-04-05 02:11:22 +01:00
committed by GitHub
parent 5f7f528083
commit 9ededef945
4 changed files with 99 additions and 33 deletions
@@ -248,9 +248,10 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
]);
}).toErrorDev(
[
'Expected server HTML to contain a matching <span> in <span>',
'An error occurred during hydration. The server HTML was replaced with client content in <div>.',
],
{withoutStack: true},
{withoutStack: 1},
);
} else {
// This used to not warn.
@@ -336,9 +337,10 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
]);
}).toErrorDev(
[
'Did not expect server HTML to contain the text node "Server" in <span>',
'An error occurred during hydration. The server HTML was replaced with client content in <div>.',
],
{withoutStack: true},
{withoutStack: 1},
);
} else {
// This used to not warn.
@@ -389,9 +391,10 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
]);
}).toErrorDev(
[
'Expected server HTML to contain a matching text node for "Client" in <span>.',
'An error occurred during hydration. The server HTML was replaced with client content in <div>.',
],
{withoutStack: true},
{withoutStack: 1},
);
} else {
// This used to not warn.
@@ -445,9 +448,10 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
]);
}).toErrorDev(
[
'Did not expect server HTML to contain the text node "Server" in <span>.',
'An error occurred during hydration. The server HTML was replaced with client content in <div>.',
],
{withoutStack: true},
{withoutStack: 1},
);
} else {
// This used to not warn.
@@ -500,9 +504,10 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
]);
}).toErrorDev(
[
'Expected server HTML to contain a matching text node for "Client" in <span>.',
'An error occurred during hydration. The server HTML was replaced with client content in <div>.',
],
{withoutStack: true},
{withoutStack: 1},
);
} else {
// This used to not warn.
@@ -630,9 +635,10 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
]);
}).toErrorDev(
[
'Expected server HTML to contain a matching <p> in <div>.',
'An error occurred during hydration. The server HTML was replaced with client content in <div>.',
],
{withoutStack: true},
{withoutStack: 1},
);
} else {
// This used to not warn.
@@ -681,9 +687,10 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
]);
}).toErrorDev(
[
'Did not expect server HTML to contain a <p> in <div>.',
'An error occurred during hydration. The server HTML was replaced with client content in <div>.',
],
{withoutStack: true},
{withoutStack: 1},
);
} else {
// This used to not warn.
+31 -12
View File
@@ -62,6 +62,7 @@ import dangerousStyleValue from '../shared/dangerousStyleValue';
import {retryIfBlockedOn} from '../events/ReactDOMEventReplaying';
import {
enableClientRenderFallbackOnHydrationMismatch,
enableSuspenseServerRenderer,
enableCreateEventHandleAPI,
enableScopeAPI,
@@ -1004,14 +1005,20 @@ export function didNotHydrateInstance(
parentProps: Props,
parentInstance: Instance,
instance: HydratableInstance,
isConcurrentMode: boolean,
) {
if (__DEV__ && parentProps[SUPPRESS_HYDRATION_WARNING] !== true) {
if (instance.nodeType === ELEMENT_NODE) {
warnForDeletedHydratableElement(parentInstance, (instance: any));
} else if (instance.nodeType === COMMENT_NODE) {
// TODO: warnForDeletedHydratableSuspenseBoundary
} else {
warnForDeletedHydratableText(parentInstance, (instance: any));
if (__DEV__) {
if (
(enableClientRenderFallbackOnHydrationMismatch && isConcurrentMode) ||
parentProps[SUPPRESS_HYDRATION_WARNING] !== true
) {
if (instance.nodeType === ELEMENT_NODE) {
warnForDeletedHydratableElement(parentInstance, (instance: any));
} else if (instance.nodeType === COMMENT_NODE) {
// TODO: warnForDeletedHydratableSuspenseBoundary
} else {
warnForDeletedHydratableText(parentInstance, (instance: any));
}
}
}
}
@@ -1082,9 +1089,15 @@ export function didNotFindHydratableInstance(
parentInstance: Instance,
type: string,
props: Props,
isConcurrentMode: boolean,
) {
if (__DEV__ && parentProps[SUPPRESS_HYDRATION_WARNING] !== true) {
warnForInsertedHydratedElement(parentInstance, type, props);
if (__DEV__) {
if (
(enableClientRenderFallbackOnHydrationMismatch && isConcurrentMode) ||
parentProps[SUPPRESS_HYDRATION_WARNING] !== true
) {
warnForInsertedHydratedElement(parentInstance, type, props);
}
}
}
@@ -1093,9 +1106,15 @@ export function didNotFindHydratableTextInstance(
parentProps: Props,
parentInstance: Instance,
text: string,
isConcurrentMode: boolean,
) {
if (__DEV__ && parentProps[SUPPRESS_HYDRATION_WARNING] !== true) {
warnForInsertedHydratedText(parentInstance, text);
if (__DEV__) {
if (
(enableClientRenderFallbackOnHydrationMismatch && isConcurrentMode) ||
parentProps[SUPPRESS_HYDRATION_WARNING] !== true
) {
warnForInsertedHydratedText(parentInstance, text);
}
}
}
@@ -1104,7 +1123,7 @@ export function didNotFindHydratableSuspenseInstance(
parentProps: Props,
parentInstance: Instance,
) {
if (__DEV__ && parentProps[SUPPRESS_HYDRATION_WARNING] !== true) {
if (__DEV__) {
// TODO: warnForInsertedHydratedSuspense(parentInstance);
}
}
@@ -148,21 +148,26 @@ function warnUnhydratedInstance(
) {
if (__DEV__) {
switch (returnFiber.tag) {
case HostRoot:
case HostRoot: {
didNotHydrateInstanceWithinContainer(
returnFiber.stateNode.containerInfo,
instance,
);
break;
case HostComponent:
}
case HostComponent: {
const isConcurrentMode = (returnFiber.mode & ConcurrentMode) !== NoMode;
didNotHydrateInstance(
returnFiber.type,
returnFiber.memoizedProps,
returnFiber.stateNode,
instance,
// TODO: Delete this argument when we remove the legacy root API.
isConcurrentMode,
);
break;
case SuspenseComponent:
}
case SuspenseComponent: {
const suspenseState: SuspenseState = returnFiber.memoizedState;
if (suspenseState.dehydrated !== null)
didNotHydrateInstanceWithinSuspenseInstance(
@@ -170,6 +175,7 @@ function warnUnhydratedInstance(
instance,
);
break;
}
}
}
}
@@ -234,33 +240,44 @@ function warnNonhydratedInstance(returnFiber: Fiber, fiber: Fiber) {
const parentProps = returnFiber.memoizedProps;
const parentInstance = returnFiber.stateNode;
switch (fiber.tag) {
case HostComponent:
case HostComponent: {
const type = fiber.type;
const props = fiber.pendingProps;
const isConcurrentMode =
(returnFiber.mode & ConcurrentMode) !== NoMode;
didNotFindHydratableInstance(
parentType,
parentProps,
parentInstance,
type,
props,
// TODO: Delete this argument when we remove the legacy root API.
isConcurrentMode,
);
break;
case HostText:
}
case HostText: {
const text = fiber.pendingProps;
const isConcurrentMode =
(returnFiber.mode & ConcurrentMode) !== NoMode;
didNotFindHydratableTextInstance(
parentType,
parentProps,
parentInstance,
text,
// TODO: Delete this argument when we remove the legacy root API.
isConcurrentMode,
);
break;
case SuspenseComponent:
}
case SuspenseComponent: {
didNotFindHydratableSuspenseInstance(
parentType,
parentProps,
parentInstance,
);
break;
}
}
break;
}
@@ -476,10 +493,11 @@ function prepareToHydrateHostTextInstance(fiber: Fiber): boolean {
// hydration parent is the parent host component of this host text.
const returnFiber = hydrationParentFiber;
if (returnFiber !== null) {
const isConcurrentMode = (returnFiber.mode & ConcurrentMode) !== NoMode;
switch (returnFiber.tag) {
case HostRoot: {
const parentContainer = returnFiber.stateNode.containerInfo;
const isConcurrentMode =
(returnFiber.mode & ConcurrentMode) !== NoMode;
didNotMatchHydratedContainerTextInstance(
parentContainer,
textInstance,
@@ -493,6 +511,8 @@ function prepareToHydrateHostTextInstance(fiber: Fiber): boolean {
const parentType = returnFiber.type;
const parentProps = returnFiber.memoizedProps;
const parentInstance = returnFiber.stateNode;
const isConcurrentMode =
(returnFiber.mode & ConcurrentMode) !== NoMode;
didNotMatchHydratedTextInstance(
parentType,
parentProps,
@@ -148,21 +148,26 @@ function warnUnhydratedInstance(
) {
if (__DEV__) {
switch (returnFiber.tag) {
case HostRoot:
case HostRoot: {
didNotHydrateInstanceWithinContainer(
returnFiber.stateNode.containerInfo,
instance,
);
break;
case HostComponent:
}
case HostComponent: {
const isConcurrentMode = (returnFiber.mode & ConcurrentMode) !== NoMode;
didNotHydrateInstance(
returnFiber.type,
returnFiber.memoizedProps,
returnFiber.stateNode,
instance,
// TODO: Delete this argument when we remove the legacy root API.
isConcurrentMode,
);
break;
case SuspenseComponent:
}
case SuspenseComponent: {
const suspenseState: SuspenseState = returnFiber.memoizedState;
if (suspenseState.dehydrated !== null)
didNotHydrateInstanceWithinSuspenseInstance(
@@ -170,6 +175,7 @@ function warnUnhydratedInstance(
instance,
);
break;
}
}
}
}
@@ -234,33 +240,44 @@ function warnNonhydratedInstance(returnFiber: Fiber, fiber: Fiber) {
const parentProps = returnFiber.memoizedProps;
const parentInstance = returnFiber.stateNode;
switch (fiber.tag) {
case HostComponent:
case HostComponent: {
const type = fiber.type;
const props = fiber.pendingProps;
const isConcurrentMode =
(returnFiber.mode & ConcurrentMode) !== NoMode;
didNotFindHydratableInstance(
parentType,
parentProps,
parentInstance,
type,
props,
// TODO: Delete this argument when we remove the legacy root API.
isConcurrentMode,
);
break;
case HostText:
}
case HostText: {
const text = fiber.pendingProps;
const isConcurrentMode =
(returnFiber.mode & ConcurrentMode) !== NoMode;
didNotFindHydratableTextInstance(
parentType,
parentProps,
parentInstance,
text,
// TODO: Delete this argument when we remove the legacy root API.
isConcurrentMode,
);
break;
case SuspenseComponent:
}
case SuspenseComponent: {
didNotFindHydratableSuspenseInstance(
parentType,
parentProps,
parentInstance,
);
break;
}
}
break;
}
@@ -476,10 +493,11 @@ function prepareToHydrateHostTextInstance(fiber: Fiber): boolean {
// hydration parent is the parent host component of this host text.
const returnFiber = hydrationParentFiber;
if (returnFiber !== null) {
const isConcurrentMode = (returnFiber.mode & ConcurrentMode) !== NoMode;
switch (returnFiber.tag) {
case HostRoot: {
const parentContainer = returnFiber.stateNode.containerInfo;
const isConcurrentMode =
(returnFiber.mode & ConcurrentMode) !== NoMode;
didNotMatchHydratedContainerTextInstance(
parentContainer,
textInstance,
@@ -493,6 +511,8 @@ function prepareToHydrateHostTextInstance(fiber: Fiber): boolean {
const parentType = returnFiber.type;
const parentProps = returnFiber.memoizedProps;
const parentInstance = returnFiber.stateNode;
const isConcurrentMode =
(returnFiber.mode & ConcurrentMode) !== NoMode;
didNotMatchHydratedTextInstance(
parentType,
parentProps,