diff --git a/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js b/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js
index 6064ad9312e87..dab01e4bd9779 100644
--- a/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js
+++ b/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js
@@ -2417,17 +2417,17 @@ describe('ReactDOMFizzServer', () => {
ReactDOMClient.hydrateRoot(container, , {
onRecoverableError(error) {
- Scheduler.log(
- 'Log recoverable error: ' + normalizeError(error.message),
- );
+ Scheduler.log('onRecoverableError: ' + normalizeError(error.message));
+ if (error.cause) {
+ Scheduler.log('Cause: ' + normalizeError(error.cause.message));
+ }
},
});
// The first paint switches to client rendering due to mismatch
await waitForPaint([
'client',
- "Log recoverable error: Hydration failed because the server rendered HTML didn't match the client.",
- 'Log recoverable error: There was an error while hydrating.',
+ "onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.",
]);
expect(getVisibleChildren(container)).toEqual(
client
);
});
@@ -2489,9 +2489,7 @@ describe('ReactDOMFizzServer', () => {
ReactDOMClient.hydrateRoot(container, , {
onRecoverableError(error) {
- Scheduler.log(
- 'Log recoverable error: ' + normalizeError(error.message),
- );
+ Scheduler.log('onRecoverableError: ' + normalizeError(error.message));
},
});
@@ -2499,8 +2497,7 @@ describe('ReactDOMFizzServer', () => {
// The first paint switches to client rendering due to mismatch
await waitForPaint([
'client',
- "Log recoverable error: Hydration failed because the server rendered HTML didn't match the client.",
- 'Log recoverable error: There was an error while hydrating.',
+ "onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.",
]);
expect(getVisibleChildren(container)).toEqual(
client
);
});
@@ -2561,7 +2558,10 @@ describe('ReactDOMFizzServer', () => {
isClient = true;
ReactDOMClient.hydrateRoot(container, , {
onRecoverableError(error) {
- Scheduler.log(normalizeError(error.message));
+ Scheduler.log('onRecoverableError: ' + normalizeError(error.message));
+ if (error.cause) {
+ Scheduler.log('Cause: ' + normalizeError(error.cause.message));
+ }
},
});
@@ -2569,8 +2569,8 @@ describe('ReactDOMFizzServer', () => {
// to client rendering.
await waitForAll([
'Yay!',
- 'Hydration error',
- 'There was an error while hydrating.',
+ 'onRecoverableError: There was an error while hydrating but React was able to recover by instead client rendering the entire root.',
+ 'Cause: Hydration error',
]);
expect(getVisibleChildren(container)).toEqual(Yay!);
@@ -2736,7 +2736,10 @@ describe('ReactDOMFizzServer', () => {
isClient = true;
ReactDOMClient.hydrateRoot(container, , {
onRecoverableError(error) {
- Scheduler.log(normalizeError(error.message));
+ Scheduler.log('onRecoverableError: ' + normalizeError(error.message));
+ if (error.cause) {
+ Scheduler.log('Cause: ' + normalizeError(error.cause.message));
+ }
},
});
@@ -2744,8 +2747,8 @@ describe('ReactDOMFizzServer', () => {
// to client rendering.
await waitForAll([
'Yay!',
- 'Hydration error',
- 'There was an error while hydrating this Suspense boundary.',
+ 'onRecoverableError: There was an error while hydrating but React was able to recover by instead client rendering from the nearest Suspense boundary.',
+ 'Cause: Hydration error',
]);
expect(getVisibleChildren(container)).toEqual(
@@ -2884,7 +2887,10 @@ describe('ReactDOMFizzServer', () => {
isClient = true;
ReactDOMClient.hydrateRoot(container, , {
onRecoverableError(error) {
- Scheduler.log('[c!] ' + error.message);
+ Scheduler.log('onRecoverableError: ' + error.message);
+ if (error.cause) {
+ Scheduler.log('Cause: ' + normalizeError(error.cause.message));
+ }
},
});
// This should not report any errors yet.
@@ -2908,7 +2914,7 @@ describe('ReactDOMFizzServer', () => {
});
await waitForAll([
'Yay!',
- '[c!] The server could not finish this Suspense boundary, ' +
+ 'onRecoverableError: The server could not finish this Suspense boundary, ' +
'likely due to an error during server rendering. ' +
'Switched to client rendering.',
]);
@@ -2969,7 +2975,10 @@ describe('ReactDOMFizzServer', () => {
isClient = true;
const root = ReactDOMClient.hydrateRoot(container, , {
onRecoverableError(error) {
- Scheduler.log('[c!] ' + error.message);
+ Scheduler.log('onRecoverableError: ' + error.message);
+ if (error.cause) {
+ Scheduler.log('Cause: ' + normalizeError(error.cause.message));
+ }
},
});
// This should not report any errors yet.
@@ -3002,7 +3011,7 @@ describe('ReactDOMFizzServer', () => {
});
await waitForAll([
'Yay! (red)',
- '[c!] The server could not finish this Suspense boundary, ' +
+ 'onRecoverableError: The server could not finish this Suspense boundary, ' +
'likely due to an error during server rendering. ' +
'Switched to client rendering.',
'Yay! (blue)',
@@ -3072,7 +3081,10 @@ describe('ReactDOMFizzServer', () => {
,
{
onRecoverableError(error) {
- Scheduler.log('[c!] ' + error.message);
+ Scheduler.log('onRecoverableError: ' + error.message);
+ if (error.cause) {
+ Scheduler.log('Cause: ' + normalizeError(error.cause.message));
+ }
},
},
);
@@ -3097,7 +3109,7 @@ describe('ReactDOMFizzServer', () => {
await waitForAll([]);
jest.runAllTimers();
assertLog([
- '[c!] The server could not finish this Suspense boundary, ' +
+ 'onRecoverableError: The server could not finish this Suspense boundary, ' +
'likely due to an error during server rendering. ' +
'Switched to client rendering.',
]);
@@ -3191,15 +3203,18 @@ describe('ReactDOMFizzServer', () => {
isClient = true;
ReactDOMClient.hydrateRoot(container, , {
onRecoverableError(error) {
- Scheduler.log(normalizeError(error.message));
+ Scheduler.log('onRecoverableError: ' + normalizeError(error.message));
+ if (error.cause) {
+ Scheduler.log('Cause: ' + normalizeError(error.cause.message));
+ }
},
});
// An error logged but instead of surfacing it to the UI, we switched
// to client rendering.
await waitForAll([
- 'Hydration error',
- 'There was an error while hydrating this Suspense boundary.',
+ 'onRecoverableError: There was an error while hydrating but React was able to recover by instead client rendering from the nearest Suspense boundary.',
+ 'Cause: Hydration error',
]);
expect(getVisibleChildren(container)).toEqual(
@@ -3259,9 +3274,10 @@ describe('ReactDOMFizzServer', () => {
const root = ReactDOMClient.createRoot(container, {
onRecoverableError(error) {
- Scheduler.log(
- 'Logged a recoverable error: ' + normalizeError(error.message),
- );
+ Scheduler.log('onRecoverableError: ' + normalizeError(error.message));
+ if (error.cause) {
+ Scheduler.log('Cause: ' + normalizeError(error.cause.message));
+ }
},
});
React.startTransition(() => {
@@ -3281,7 +3297,8 @@ describe('ReactDOMFizzServer', () => {
'B',
// Log the error
- 'Logged a recoverable error: Oops!',
+ 'onRecoverableError: There was an error during concurrent rendering but React was able to recover by instead synchronously rendering the entire root.',
+ 'Cause: Oops!',
]);
// UI looks normal
@@ -3337,9 +3354,10 @@ describe('ReactDOMFizzServer', () => {
isClient = true;
ReactDOMClient.hydrateRoot(container, , {
onRecoverableError(error) {
- Scheduler.log(
- 'Logged recoverable error: ' + normalizeError(error.message),
- );
+ Scheduler.log('onRecoverableError: ' + normalizeError(error.message));
+ if (error.cause) {
+ Scheduler.log('Cause: ' + normalizeError(error.cause.message));
+ }
},
});
@@ -3347,13 +3365,11 @@ describe('ReactDOMFizzServer', () => {
'A',
'B',
- 'Logged recoverable error: Hydration error',
- 'Logged recoverable error: There was an error while hydrating this ' +
- 'Suspense boundary.',
+ 'onRecoverableError: There was an error while hydrating but React was able to recover by instead client rendering from the nearest Suspense boundary.',
+ 'Cause: Hydration error',
- 'Logged recoverable error: Hydration error',
- 'Logged recoverable error: There was an error while hydrating this ' +
- 'Suspense boundary.',
+ 'onRecoverableError: There was an error while hydrating but React was able to recover by instead client rendering from the nearest Suspense boundary.',
+ 'Cause: Hydration error',
]);
});
@@ -4399,9 +4415,10 @@ describe('ReactDOMFizzServer', () => {
const [ClientApp, clientResolve] = makeApp();
ReactDOMClient.hydrateRoot(container, , {
onRecoverableError(error) {
- Scheduler.log(
- 'Logged recoverable error: ' + normalizeError(error.message),
- );
+ Scheduler.log('onRecoverableError: ' + normalizeError(error.message));
+ if (error.cause) {
+ Scheduler.log('Cause: ' + normalizeError(error.cause.message));
+ }
},
});
await waitForAll([]);
@@ -4478,9 +4495,10 @@ describe('ReactDOMFizzServer', () => {
const [ClientApp, clientResolve] = makeApp();
ReactDOMClient.hydrateRoot(container, , {
onRecoverableError(error) {
- Scheduler.log(
- 'Logged recoverable error: ' + normalizeError(error.message),
- );
+ Scheduler.log('onRecoverableError: ' + normalizeError(error.message));
+ if (error.cause) {
+ Scheduler.log('Cause: ' + normalizeError(error.cause.message));
+ }
},
});
await waitForAll([]);
@@ -4496,8 +4514,7 @@ describe('ReactDOMFizzServer', () => {
// client-side rendering.
await clientResolve();
await waitForAll([
- "Logged recoverable error: Hydration failed because the server rendered HTML didn't match the client.",
- 'Logged recoverable error: There was an error while hydrating this Suspense boundary.',
+ "onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.",
]);
expect(getVisibleChildren(container)).toEqual(
@@ -4545,14 +4562,14 @@ describe('ReactDOMFizzServer', () => {
ReactDOMClient.hydrateRoot(container, , {
onRecoverableError(error) {
- Scheduler.log(
- 'Logged recoverable error: ' + normalizeError(error.message),
- );
+ Scheduler.log('onRecoverableError: ' + normalizeError(error.message));
+ if (error.cause) {
+ Scheduler.log('Cause: ' + normalizeError(error.cause.message));
+ }
},
});
await waitForAll([
- "Logged recoverable error: Hydration failed because the server rendered HTML didn't match the client.",
- 'Logged recoverable error: There was an error while hydrating this Suspense boundary.',
+ "onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.",
]);
expect(getVisibleChildren(container)).toEqual(
@@ -4620,14 +4637,15 @@ describe('ReactDOMFizzServer', () => {
ReactDOMClient.hydrateRoot(container, , {
onRecoverableError(error) {
- Scheduler.log(
- 'Logged recoverable error: ' + normalizeError(error.message),
- );
+ Scheduler.log('onRecoverableError: ' + normalizeError(error.message));
+ if (error.cause) {
+ Scheduler.log('Cause: ' + normalizeError(error.cause.message));
+ }
},
});
await waitForAll([
- 'Logged recoverable error: uh oh',
- 'Logged recoverable error: There was an error while hydrating this Suspense boundary.',
+ 'onRecoverableError: There was an error while hydrating but React was able to recover by instead client rendering from the nearest Suspense boundary.',
+ 'Cause: uh oh',
]);
expect(getVisibleChildren(container)).toEqual(
@@ -4709,9 +4727,10 @@ describe('ReactDOMFizzServer', () => {
ReactDOMClient.hydrateRoot(container, , {
onRecoverableError(error) {
- Scheduler.log(
- 'Logged recoverable error: ' + normalizeError(error.message),
- );
+ Scheduler.log('onRecoverableError: ' + normalizeError(error.message));
+ if (error.cause) {
+ Scheduler.log('Cause: ' + normalizeError(error.cause.message));
+ }
},
});
await waitForAll([
@@ -4719,8 +4738,8 @@ describe('ReactDOMFizzServer', () => {
// onRecoverableError because the UI recovered without surfacing the
// error to the user.
- 'Logged recoverable error: first error',
- 'Logged recoverable error: There was an error while hydrating this Suspense boundary.',
+ 'onRecoverableError: There was an error while hydrating but React was able to recover by instead client rendering from the nearest Suspense boundary.',
+ 'Cause: first error',
]);
expect(mockError.mock.calls).toEqual([]);
mockError.mockClear();
@@ -4828,9 +4847,10 @@ describe('ReactDOMFizzServer', () => {
ReactDOMClient.hydrateRoot(container, , {
onRecoverableError(error) {
- Scheduler.log(
- 'Logged recoverable error: ' + normalizeError(error.message),
- );
+ Scheduler.log('onRecoverableError: ' + normalizeError(error.message));
+ if (error.cause) {
+ Scheduler.log('Cause: ' + normalizeError(error.cause.message));
+ }
},
});
await waitForAll(['suspending']);
@@ -4846,8 +4866,8 @@ describe('ReactDOMFizzServer', () => {
await unsuspend();
await waitForAll([
'throwing: first error',
- 'Logged recoverable error: first error',
- 'Logged recoverable error: There was an error while hydrating this Suspense boundary.',
+ 'onRecoverableError: There was an error while hydrating but React was able to recover by instead client rendering from the nearest Suspense boundary.',
+ 'Cause: first error',
]);
expect(getVisibleChildren(container)).toEqual(
@@ -4954,16 +4974,17 @@ describe('ReactDOMFizzServer', () => {
ReactDOMClient.hydrateRoot(container, , {
onRecoverableError(error) {
- Scheduler.log(
- 'Logged recoverable error: ' + normalizeError(error.message),
- );
+ Scheduler.log('onRecoverableError: ' + normalizeError(error.message));
+ if (error.cause) {
+ Scheduler.log('Cause: ' + normalizeError(error.cause.message));
+ }
},
});
await waitForAll([
'throwing: first error',
'suspending',
- 'Logged recoverable error: first error',
- 'Logged recoverable error: There was an error while hydrating this Suspense boundary.',
+ 'onRecoverableError: There was an error while hydrating but React was able to recover by instead client rendering from the nearest Suspense boundary.',
+ 'Cause: first error',
]);
expect(mockError.mock.calls).toEqual([]);
mockError.mockClear();
@@ -5368,7 +5389,10 @@ describe('ReactDOMFizzServer', () => {
const errors = [];
ReactDOMClient.hydrateRoot(container, , {
onRecoverableError(error) {
- errors.push(error.message);
+ errors.push('onRecoverableError: ' + normalizeError(error.message));
+ if (error.cause) {
+ Scheduler.log('Cause: ' + normalizeError(error.cause.message));
+ }
},
});
await waitForAll([]);
@@ -6336,7 +6360,7 @@ describe('ReactDOMFizzServer', () => {
},
});
await waitForAll([]);
- expect(errors.length).toEqual(2);
+ expect(errors.length).toEqual(1);
expect(getVisibleChildren(container)).toEqual();
});
});
diff --git a/packages/react-dom/src/__tests__/ReactDOMFizzShellHydration-test.js b/packages/react-dom/src/__tests__/ReactDOMFizzShellHydration-test.js
index 756d5d455c9d2..f4df63ca7a652 100644
--- a/packages/react-dom/src/__tests__/ReactDOMFizzShellHydration-test.js
+++ b/packages/react-dom/src/__tests__/ReactDOMFizzShellHydration-test.js
@@ -397,6 +397,9 @@ describe('ReactDOMFizzShellHydration', () => {
},
onRecoverableError(error) {
Scheduler.log('onRecoverableError: ' + error.message);
+ if (error.cause) {
+ Scheduler.log('Cause: ' + error.cause.message);
+ }
},
});
});
@@ -462,6 +465,9 @@ describe('ReactDOMFizzShellHydration', () => {
},
onRecoverableError(error) {
Scheduler.log('onRecoverableError: ' + error.message);
+ if (error.cause) {
+ Scheduler.log('Cause: ' + error.cause.message);
+ }
},
});
});
@@ -529,13 +535,16 @@ describe('ReactDOMFizzShellHydration', () => {
},
onRecoverableError(error) {
Scheduler.log('onRecoverableError: ' + error.message);
+ if (error.cause) {
+ Scheduler.log('Cause: ' + error.cause.message);
+ }
},
});
});
assertLog([
- 'onRecoverableError: plain error',
- 'onRecoverableError: There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.',
+ 'onRecoverableError: There was an error while hydrating but React was able to recover by instead client rendering the entire root.',
+ 'Cause: plain error',
]);
expect(container.textContent).toBe('Hello world');
});
diff --git a/packages/react-dom/src/__tests__/ReactDOMFizzSuppressHydrationWarning-test.js b/packages/react-dom/src/__tests__/ReactDOMFizzSuppressHydrationWarning-test.js
index 7a584d1797d92..7f893234c6135 100644
--- a/packages/react-dom/src/__tests__/ReactDOMFizzSuppressHydrationWarning-test.js
+++ b/packages/react-dom/src/__tests__/ReactDOMFizzSuppressHydrationWarning-test.js
@@ -165,7 +165,10 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
ReactDOMClient.hydrateRoot(container, , {
onRecoverableError(error) {
// Don't miss a hydration error. There should be none.
- Scheduler.log(normalizeError(error.message));
+ Scheduler.log('onRecoverableError: ' + normalizeError(error.message));
+ if (error.cause) {
+ Scheduler.log('Cause: ' + normalizeError(error.cause.message));
+ }
},
});
await waitForAll([]);
@@ -205,7 +208,10 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
);
ReactDOMClient.hydrateRoot(container, , {
onRecoverableError(error) {
- Scheduler.log(normalizeError(error.message));
+ Scheduler.log('onRecoverableError: ' + normalizeError(error.message));
+ if (error.cause) {
+ Scheduler.log('Cause: ' + normalizeError(error.cause.message));
+ }
},
});
await waitForAll([]);
@@ -246,12 +252,14 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
);
ReactDOMClient.hydrateRoot(container, , {
onRecoverableError(error) {
- Scheduler.log(normalizeError(error.message));
+ Scheduler.log('onRecoverableError: ' + normalizeError(error.message));
+ if (error.cause) {
+ Scheduler.log('Cause: ' + normalizeError(error.cause.message));
+ }
},
});
await waitForAll([
- "Hydration failed because the server rendered HTML didn't match the client.",
- 'There was an error while hydrating.',
+ "onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.",
]);
expect(getVisibleChildren(container)).toEqual(
@@ -283,7 +291,10 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
);
const root = ReactDOMClient.hydrateRoot(container, , {
onRecoverableError(error) {
- Scheduler.log(normalizeError(error.message));
+ Scheduler.log('onRecoverableError: ' + normalizeError(error.message));
+ if (error.cause) {
+ Scheduler.log('Cause: ' + normalizeError(error.cause.message));
+ }
},
});
await waitForAll([]);
@@ -327,12 +338,14 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
);
ReactDOMClient.hydrateRoot(container, , {
onRecoverableError(error) {
- Scheduler.log(normalizeError(error.message));
+ Scheduler.log('onRecoverableError: ' + normalizeError(error.message));
+ if (error.cause) {
+ Scheduler.log('Cause: ' + normalizeError(error.cause.message));
+ }
},
});
await waitForAll([
- "Hydration failed because the server rendered HTML didn't match the client.",
- 'There was an error while hydrating.',
+ "onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.",
]);
expect(getVisibleChildren(container)).toEqual(
@@ -367,12 +380,14 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
);
ReactDOMClient.hydrateRoot(container, , {
onRecoverableError(error) {
- Scheduler.log(normalizeError(error.message));
+ Scheduler.log('onRecoverableError: ' + normalizeError(error.message));
+ if (error.cause) {
+ Scheduler.log('Cause: ' + normalizeError(error.cause.message));
+ }
},
});
await waitForAll([
- "Hydration failed because the server rendered HTML didn't match the client.",
- 'There was an error while hydrating.',
+ "onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.",
]);
expect(getVisibleChildren(container)).toEqual(
@@ -410,12 +425,14 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
);
ReactDOMClient.hydrateRoot(container, , {
onRecoverableError(error) {
- Scheduler.log(normalizeError(error.message));
+ Scheduler.log('onRecoverableError: ' + normalizeError(error.message));
+ if (error.cause) {
+ Scheduler.log('Cause: ' + normalizeError(error.cause.message));
+ }
},
});
await waitForAll([
- "Hydration failed because the server rendered HTML didn't match the client.",
- 'There was an error while hydrating.',
+ "onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.",
]);
expect(getVisibleChildren(container)).toEqual(
@@ -451,12 +468,14 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
);
ReactDOMClient.hydrateRoot(container, , {
onRecoverableError(error) {
- Scheduler.log(normalizeError(error.message));
+ Scheduler.log('onRecoverableError: ' + normalizeError(error.message));
+ if (error.cause) {
+ Scheduler.log('Cause: ' + normalizeError(error.cause.message));
+ }
},
});
await waitForAll([
- "Hydration failed because the server rendered HTML didn't match the client.",
- 'There was an error while hydrating.',
+ "onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.",
]);
expect(getVisibleChildren(container)).toEqual(
@@ -496,7 +515,10 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
);
ReactDOMClient.hydrateRoot(container, , {
onRecoverableError(error) {
- Scheduler.log(normalizeError(error.message));
+ Scheduler.log('onRecoverableError: ' + normalizeError(error.message));
+ if (error.cause) {
+ Scheduler.log('Cause: ' + normalizeError(error.cause.message));
+ }
},
});
await waitForAll([]);
@@ -533,7 +555,10 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
);
ReactDOMClient.hydrateRoot(container, , {
onRecoverableError(error) {
- Scheduler.log(normalizeError(error.message));
+ Scheduler.log('onRecoverableError: ' + normalizeError(error.message));
+ if (error.cause) {
+ Scheduler.log('Cause: ' + normalizeError(error.cause.message));
+ }
},
});
await waitForAll([]);
@@ -566,12 +591,14 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
);
ReactDOMClient.hydrateRoot(container, , {
onRecoverableError(error) {
- Scheduler.log(normalizeError(error.message));
+ Scheduler.log('onRecoverableError: ' + normalizeError(error.message));
+ if (error.cause) {
+ Scheduler.log('Cause: ' + normalizeError(error.cause.message));
+ }
},
});
await waitForAll([
- "Hydration failed because the server rendered HTML didn't match the client.",
- 'There was an error while hydrating.',
+ "onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.",
]);
expect(getVisibleChildren(container)).toEqual(
@@ -604,12 +631,14 @@ describe('ReactDOMFizzServerHydrationWarning', () => {
);
ReactDOMClient.hydrateRoot(container, , {
onRecoverableError(error) {
- Scheduler.log(normalizeError(error.message));
+ Scheduler.log('onRecoverableError: ' + normalizeError(error.message));
+ if (error.cause) {
+ Scheduler.log('Cause: ' + normalizeError(error.cause.message));
+ }
},
});
await waitForAll([
- "Hydration failed because the server rendered HTML didn't match the client.",
- 'There was an error while hydrating.',
+ "onRecoverableError: Hydration failed because the server rendered HTML didn't match the client.",
]);
expect(getVisibleChildren(container)).toEqual(
diff --git a/packages/react-dom/src/__tests__/ReactDOMHydrationDiff-test.js b/packages/react-dom/src/__tests__/ReactDOMHydrationDiff-test.js
index 07cbcbf9bed34..147a84207947c 100644
--- a/packages/react-dom/src/__tests__/ReactDOMHydrationDiff-test.js
+++ b/packages/react-dom/src/__tests__/ReactDOMHydrationDiff-test.js
@@ -55,6 +55,15 @@ describe('ReactDOMServerHydration', () => {
function formatMessage(args) {
const [format, ...rest] = args;
if (format instanceof Error) {
+ if (format.cause instanceof Error) {
+ return (
+ 'Caught [' +
+ format.message +
+ ']\n Cause [' +
+ format.cause.message +
+ ']'
+ );
+ }
return 'Caught [' + format.message + ']';
}
rest[rest.length - 1] = normalizeCodeLocInfo(rest[rest.length - 1]);
@@ -88,28 +97,27 @@ describe('ReactDOMServerHydration', () => {
}
if (gate(flags => flags.favorSafetyOverHydrationPerf)) {
expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`
- [
- "Caught [Hydration failed because the server rendered HTML didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used:
-
- - A server/client branch \`if (typeof window !== 'undefined')\`.
- - Variable input such as \`Date.now()\` or \`Math.random()\` which changes each time it's called.
- - Date formatting in a user's locale which doesn't match the server.
- - External changing data without sending a snapshot of it along with the HTML.
- - Invalid HTML tag nesting.
-
- It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.
-
- https://react.dev/link/hydration-mismatch
-
-
-
-
- + client
- - server
- ]",
- "Caught [There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.]",
- ]
- `);
+ [
+ "Caught [Hydration failed because the server rendered HTML didn't match the client. As a result this tree will be regenerated on the client. This can happen if a SSR-ed Client Component used:
+
+ - A server/client branch \`if (typeof window !== 'undefined')\`.
+ - Variable input such as \`Date.now()\` or \`Math.random()\` which changes each time it's called.
+ - Date formatting in a user's locale which doesn't match the server.
+ - External changing data without sending a snapshot of it along with the HTML.
+ - Invalid HTML tag nesting.
+
+ It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.
+
+ https://react.dev/link/hydration-mismatch
+
+
+
+
+ + client
+ - server
+ ]",
+ ]
+ `);
} else {
expect(testMismatch(Mismatch)).toMatchInlineSnapshot(`
[
@@ -170,7 +178,6 @@ describe('ReactDOMServerHydration', () => {
+ This markup contains an nbsp entity: client text
- This markup contains an nbsp entity: server text
]",
- "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 {
@@ -477,7 +484,6 @@ describe('ReactDOMServerHydration', () => {
+
]",
- "Caught [There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.]",
]
`);
});
@@ -513,7 +519,6 @@ describe('ReactDOMServerHydration', () => {
-
...
]",
- "Caught [There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.]",
]
`);
});
@@ -550,7 +555,6 @@ describe('ReactDOMServerHydration', () => {
-