),
renderBrowser: () => (
// The inner element type is different from the server render, but the inner text is the same.
-
-
SSRMismatchTest default text
+
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ SSRMismatchTest default text
+ 7
+ 8
+ 9
+ 10
+ 11
+ 12
),
},
diff --git a/packages/react-dom/src/client/ReactDOM.js b/packages/react-dom/src/client/ReactDOM.js
index a2576e2e706d7..839770cbff379 100644
--- a/packages/react-dom/src/client/ReactDOM.js
+++ b/packages/react-dom/src/client/ReactDOM.js
@@ -948,7 +948,7 @@ const DOMRenderer = ReactFiberReconciler({
props: Props,
) {
if (__DEV__) {
- warnForInsertedHydratedElement(parentContainer, type, props);
+ warnForInsertedHydratedElement(parentContainer, type, props, 0);
}
},
@@ -967,9 +967,10 @@ const DOMRenderer = ReactFiberReconciler({
parentInstance: Instance,
type: string,
props: Props,
+ index: number,
) {
if (__DEV__ && parentProps[SUPPRESS_HYDRATION_WARNING] !== true) {
- warnForInsertedHydratedElement(parentInstance, type, props);
+ warnForInsertedHydratedElement(parentInstance, type, props, index);
}
},
diff --git a/packages/react-dom/src/client/ReactDOMFiberComponent.js b/packages/react-dom/src/client/ReactDOMFiberComponent.js
index 59d1e248bb35b..1169ea429507e 100644
--- a/packages/react-dom/src/client/ReactDOMFiberComponent.js
+++ b/packages/react-dom/src/client/ReactDOMFiberComponent.js
@@ -1146,17 +1146,64 @@ export function warnForInsertedHydratedElement(
parentNode: Element | Document,
tag: string,
props: Object,
+ index: number,
) {
if (__DEV__) {
if (didWarnInvalidHydration) {
return;
}
didWarnInvalidHydration = true;
+ let htmlContext = [];
+ const ic = parentNode.childNodes.length;
+ const parentNodeName = parentNode.nodeName.toLowerCase();
+ htmlContext.push(
+ ' <' +
+ parentNodeName +
+ (parentNode.className
+ ? ' className="' + parentNode.className + '"'
+ : '') +
+ '>',
+ );
+ if (index - 5 > 0) {
+ htmlContext.push(' …');
+ }
+ for (let i = index - 5; i <= index + 5; ++i) {
+ if (i >= 0 && i < ic) {
+ const childNode = parentNode.childNodes[i];
+ const childNodeName = childNode.nodeName.toLowerCase();
+ htmlContext.push(
+ (i === index ? '- ' : ' ') +
+ (childNode.nodeType === 1
+ ? '<' +
+ childNodeName +
+ (childNode.className
+ ? ' className="' + childNode.className + '"'
+ : '') +
+ (childNode.textContent
+ ? '>' + childNode.textContent + '' + childNodeName + '>'
+ : ' />')
+ : childNode.textContent),
+ );
+ if (i === index) {
+ htmlContext.push(
+ '+ <' +
+ tag +
+ (props.className ? ' className="' + props.className + '"' : '') +
+ ' />',
+ );
+ }
+ }
+ }
+ if (index + 5 < ic - 1) {
+ htmlContext.push(' …');
+ }
+ htmlContext.push(' ' + parentNodeName + '>');
warning(
false,
- 'Expected server HTML to contain a matching <%s> in <%s>.%s',
+ 'Expected server HTML to contain a matching <%s> in <%s>.%s%s',
tag,
- parentNode.nodeName.toLowerCase(),
+ parentNodeName,
+ '\n' + htmlContext.join('\n') + '\n',
getStack(),
);
}
diff --git a/packages/react-reconciler/src/ReactFiberHydrationContext.js b/packages/react-reconciler/src/ReactFiberHydrationContext.js
index bd3889580acf8..ccad8bab0c525 100644
--- a/packages/react-reconciler/src/ReactFiberHydrationContext.js
+++ b/packages/react-reconciler/src/ReactFiberHydrationContext.js
@@ -168,6 +168,7 @@ export default function
(
parentInstance,
type,
props,
+ fiber.index,
);
break;
case HostText:
diff --git a/packages/react-reconciler/src/ReactFiberReconciler.js b/packages/react-reconciler/src/ReactFiberReconciler.js
index 5ad78944fb50f..df37f139431ba 100644
--- a/packages/react-reconciler/src/ReactFiberReconciler.js
+++ b/packages/react-reconciler/src/ReactFiberReconciler.js
@@ -206,6 +206,7 @@ type HydrationHostConfig = {
parentInstance: I,
type: T,
props: P,
+ index: number,
): void,
didNotFindHydratableTextInstance(
parentType: T,
diff --git a/scripts/rollup/results.json b/scripts/rollup/results.json
index c59a7b3714d36..c7a28c0e8d8a3 100644
--- a/scripts/rollup/results.json
+++ b/scripts/rollup/results.json
@@ -46,22 +46,22 @@
"filename": "react-dom.development.js",
"bundleType": "UMD_DEV",
"packageName": "react-dom",
- "size": 591567,
- "gzip": 138758
+ "size": 592727,
+ "gzip": 139090
},
{
"filename": "react-dom.production.min.js",
"bundleType": "UMD_PROD",
"packageName": "react-dom",
- "size": 96778,
- "gzip": 31445
+ "size": 96782,
+ "gzip": 31444
},
{
"filename": "react-dom.development.js",
"bundleType": "NODE_DEV",
"packageName": "react-dom",
- "size": 575580,
- "gzip": 134533
+ "size": 576740,
+ "gzip": 134864
},
{
"filename": "react-dom.production.min.js",
@@ -74,8 +74,8 @@
"filename": "ReactDOM-dev.js",
"bundleType": "FB_DEV",
"packageName": "react-dom",
- "size": 594873,
- "gzip": 136788
+ "size": 596363,
+ "gzip": 137178
},
{
"filename": "ReactDOM-prod.js",
@@ -221,8 +221,8 @@
"filename": "react-art.development.js",
"bundleType": "UMD_DEV",
"packageName": "react-art",
- "size": 389869,
- "gzip": 86413
+ "size": 389882,
+ "gzip": 86423
},
{
"filename": "react-art.production.min.js",
@@ -235,8 +235,8 @@
"filename": "react-art.development.js",
"bundleType": "NODE_DEV",
"packageName": "react-art",
- "size": 313942,
- "gzip": 67385
+ "size": 313955,
+ "gzip": 67392
},
{
"filename": "react-art.production.min.js",
@@ -249,8 +249,8 @@
"filename": "ReactART-dev.js",
"bundleType": "FB_DEV",
"packageName": "react-art",
- "size": 318024,
- "gzip": 66603
+ "size": 318053,
+ "gzip": 66612
},
{
"filename": "ReactART-prod.js",
@@ -263,8 +263,8 @@
"filename": "ReactNativeRenderer-dev.js",
"bundleType": "RN_DEV",
"packageName": "react-native-renderer",
- "size": 443941,
- "gzip": 97414
+ "size": 443970,
+ "gzip": 97423
},
{
"filename": "ReactNativeRenderer-prod.js",
@@ -277,8 +277,8 @@
"filename": "react-test-renderer.development.js",
"bundleType": "NODE_DEV",
"packageName": "react-test-renderer",
- "size": 311062,
- "gzip": 66359
+ "size": 311075,
+ "gzip": 66366
},
{
"filename": "react-test-renderer.production.min.js",
@@ -291,8 +291,8 @@
"filename": "ReactTestRenderer-dev.js",
"bundleType": "FB_DEV",
"packageName": "react-test-renderer",
- "size": 315158,
- "gzip": 65549
+ "size": 315187,
+ "gzip": 65558
},
{
"filename": "react-test-renderer-shallow.development.js",
@@ -333,8 +333,8 @@
"filename": "react-reconciler.development.js",
"bundleType": "NODE_DEV",
"packageName": "react-reconciler",
- "size": 292377,
- "gzip": 61765
+ "size": 292390,
+ "gzip": 61771
},
{
"filename": "react-reconciler.production.min.js",
@@ -375,8 +375,8 @@
"filename": "ReactFabric-dev.js",
"bundleType": "RN_DEV",
"packageName": "react-native-renderer",
- "size": 438218,
- "gzip": 96267
+ "size": 438247,
+ "gzip": 96276
},
{
"filename": "ReactFabric-prod.js",
@@ -389,8 +389,8 @@
"filename": "react-reconciler-persistent.development.js",
"bundleType": "NODE_DEV",
"packageName": "react-reconciler",
- "size": 291949,
- "gzip": 61587
+ "size": 291962,
+ "gzip": 61594
},
{
"filename": "react-reconciler-persistent.production.min.js",