From f412666120e24b924c6f2b54d04915a8fa1aa8c9 Mon Sep 17 00:00:00 2001 From: Zack Tanner <1939140+ztanner@users.noreply.github.com> Date: Mon, 3 Feb 2025 14:11:18 -0800 Subject: [PATCH] [DevOverlay] cleanup hydration error UI (#75499) --- .../client/components/is-hydration-error.ts | 2 +- .../internal/container/errors.tsx | 3 +++ .../component-stack-pseudo-html.tsx | 25 +++++++------------ .../container/runtime-error/index.tsx | 6 ++--- .../internal/icons/collapse-icon.tsx | 17 ++++++------- .../acceptance-app/hydration-error.test.ts | 16 ++++++------ .../acceptance/hydration-error.test.ts | 14 +++++------ 7 files changed, 38 insertions(+), 45 deletions(-) diff --git a/packages/next/src/client/components/is-hydration-error.ts b/packages/next/src/client/components/is-hydration-error.ts index a066a03b68a4a..2ce93033a5baa 100644 --- a/packages/next/src/client/components/is-hydration-error.ts +++ b/packages/next/src/client/components/is-hydration-error.ts @@ -3,7 +3,7 @@ import isError from '../../lib/is-error' const hydrationErrorRegex = /hydration failed|while hydrating|content does not match|did not match|HTML didn't match/i -const reactUnifiedMismatchWarning = `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` +const reactUnifiedMismatchWarning = `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:` const reactHydrationStartMessages = [ reactUnifiedMismatchWarning, diff --git a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/container/errors.tsx b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/container/errors.tsx index c1ecae8549949..4d727e4771126 100644 --- a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/container/errors.tsx +++ b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/container/errors.tsx @@ -267,4 +267,7 @@ export const styles = css` .error-overlay-notes-container { padding: 0 var(--size-4); } + .error-overlay-notes-container p { + white-space: pre-wrap; + } ` diff --git a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/container/runtime-error/component-stack-pseudo-html.tsx b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/container/runtime-error/component-stack-pseudo-html.tsx index 8f9de819d59b0..f22c56d2d00dc 100644 --- a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/container/runtime-error/component-stack-pseudo-html.tsx +++ b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/container/runtime-error/component-stack-pseudo-html.tsx @@ -304,15 +304,13 @@ export function PseudoHtmlDiff({ return (
- - - +
         {htmlComponents}
       
@@ -371,6 +369,7 @@ export const PSEUDO_HTML_DIFF_STYLES = css` } [data-nextjs-container-errors-pseudo-html-collapse] { all: unset; + padding: var(--size-2); &:focus { outline: none; } @@ -393,16 +392,10 @@ export const PSEUDO_HTML_DIFF_STYLES = css` [data-nextjs-container-errors-pseudo-html--tag-adjacent='false'] { color: var(--color-accents-1); } - - [data-nextjs-container-errors-pseudo-html] > span { - display: block; - height: var(--size-5); - } [data-nextjs-container-errors-pseudo-html] > pre > code > span { display: block; - height: var(--size-5); + padding: var(--size-1) var(--size-4); } - .nextjs__container_errors__component-stack { margin: 0; } diff --git a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/container/runtime-error/index.tsx b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/container/runtime-error/index.tsx index 9d57674c61d31..578b09be0b3c6 100644 --- a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/container/runtime-error/index.tsx +++ b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/container/runtime-error/index.tsx @@ -8,7 +8,7 @@ import type { ReadyRuntimeError } from '../../../../internal/helpers/get-error-b export type RuntimeErrorProps = { error: ReadyRuntimeError } export function RuntimeError({ error }: RuntimeErrorProps) { - const { firstFrame } = useMemo(() => { + const firstFrame = useMemo(() => { const firstFirstPartyFrameIndex = error.frames.findIndex( (entry) => !entry.ignored && @@ -16,9 +16,7 @@ export function RuntimeError({ error }: RuntimeErrorProps) { Boolean(entry.originalStackFrame) ) - return { - firstFrame: error.frames[firstFirstPartyFrameIndex] ?? null, - } + return error.frames[firstFirstPartyFrameIndex] ?? null }, [error.frames]) return ( diff --git a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/icons/collapse-icon.tsx b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/icons/collapse-icon.tsx index 8dab41204c571..592d18cc6e706 100644 --- a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/icons/collapse-icon.tsx +++ b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/icons/collapse-icon.tsx @@ -3,21 +3,20 @@ export function CollapseIcon({ collapsed }: { collapsed?: boolean } = {}) { - + ) } diff --git a/test/development/acceptance-app/hydration-error.test.ts b/test/development/acceptance-app/hydration-error.test.ts index 108c2e8fe5364..5122691ee6746 100644 --- a/test/development/acceptance-app/hydration-error.test.ts +++ b/test/development/acceptance-app/hydration-error.test.ts @@ -76,7 +76,7 @@ describe('Error overlay for hydration errors in App router', () => { expect(await getRedboxTotalErrorCount(browser)).toBe(1) expect(await session.getRedboxDescription()).toMatchInlineSnapshot( - `"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"` + `"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:"` ) expect(await session.getRedboxDescriptionWarning()).toMatchInlineSnapshot(` @@ -173,7 +173,7 @@ describe('Error overlay for hydration errors in App router', () => { } expect(await session.getRedboxDescription()).toMatchInlineSnapshot( - `"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"` + `"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:"` ) }) @@ -209,7 +209,7 @@ describe('Error overlay for hydration errors in App router', () => { expect(pseudoHtml).toMatchInlineSnapshot(`"- className="server-html""`) expect(await session.getRedboxDescription()).toMatchInlineSnapshot( - `"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"` + `"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:"` ) }) @@ -259,7 +259,7 @@ describe('Error overlay for hydration errors in App router', () => { } expect(await session.getRedboxDescription()).toMatchInlineSnapshot( - `"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"` + `"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:"` ) }) @@ -304,7 +304,7 @@ describe('Error overlay for hydration errors in App router', () => { } expect(await session.getRedboxDescription()).toMatchInlineSnapshot( - `"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"` + `"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:"` ) }) @@ -330,7 +330,7 @@ describe('Error overlay for hydration errors in App router', () => { expect(await getRedboxTotalErrorCount(browser)).toBe(1) expect(await session.getRedboxDescription()).toMatchInlineSnapshot( - `"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"` + `"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:"` ) const pseudoHtml = await session.getRedboxComponentStack() @@ -380,7 +380,7 @@ describe('Error overlay for hydration errors in App router', () => { // FIXME: Should also have "text nodes cannot be a child of tr" expect(await session.getRedboxDescription()).toMatchInlineSnapshot( - `"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"` + `"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:"` ) const pseudoHtml = await session.getRedboxComponentStack() @@ -504,7 +504,7 @@ describe('Error overlay for hydration errors in App router', () => { } expect(await session.getRedboxDescription()).toMatchInlineSnapshot( - `"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"` + `"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:"` ) }) diff --git a/test/development/acceptance/hydration-error.test.ts b/test/development/acceptance/hydration-error.test.ts index 188a6209d616b..eb5a1da8b25e2 100644 --- a/test/development/acceptance/hydration-error.test.ts +++ b/test/development/acceptance/hydration-error.test.ts @@ -83,7 +83,7 @@ describe('Error overlay for hydration errors in Pages router', () => { ) } else { expect(await session.getRedboxDescription()).toMatchInlineSnapshot( - `"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"` + `"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:"` ) } @@ -255,7 +255,7 @@ describe('Error overlay for hydration errors in Pages router', () => { ) } else { expect(await session.getRedboxDescription()).toMatchInlineSnapshot( - `"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"` + `"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:"` ) } }) @@ -342,7 +342,7 @@ describe('Error overlay for hydration errors in Pages router', () => { ) } else { expect(await session.getRedboxDescription()).toMatchInlineSnapshot( - `"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"` + `"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:"` ) } }) @@ -412,7 +412,7 @@ describe('Error overlay for hydration errors in Pages router', () => { ) } else { expect(await session.getRedboxDescription()).toMatchInlineSnapshot( - `"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"` + `"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:"` ) } }) @@ -442,7 +442,7 @@ describe('Error overlay for hydration errors in Pages router', () => { ) } else { expect(await session.getRedboxDescription()).toMatchInlineSnapshot( - `"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"` + `"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:"` ) } @@ -532,7 +532,7 @@ describe('Error overlay for hydration errors in Pages router', () => { ) } else { expect(await session.getRedboxDescription()).toMatchInlineSnapshot( - `"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"` + `"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:"` ) } @@ -691,7 +691,7 @@ describe('Error overlay for hydration errors in Pages router', () => { ) } else { expect(await session.getRedboxDescription()).toMatchInlineSnapshot( - `"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"` + `"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:"` ) } })