Skip to content

Commit

Permalink
[DevOverlay] cleanup hydration error UI
Browse files Browse the repository at this point in the history
  • Loading branch information
ztanner committed Feb 3, 2025
1 parent 7320fd5 commit 46ace56
Show file tree
Hide file tree
Showing 7 changed files with 38 additions and 45 deletions.
2 changes: 1 addition & 1 deletion packages/next/src/client/components/is-hydration-error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
`
Original file line number Diff line number Diff line change
Expand Up @@ -304,15 +304,13 @@ export function PseudoHtmlDiff({

return (
<div data-nextjs-container-errors-pseudo-html>
<span>
<button
tabIndex={10} // match CallStackFrame
data-nextjs-container-errors-pseudo-html-collapse
onClick={() => toggleCollapseHtml(!isHtmlCollapsed)}
>
<CollapseIcon collapsed={isHtmlCollapsed} />
</button>
</span>
<button
tabIndex={10} // match CallStackFrame
data-nextjs-container-errors-pseudo-html-collapse
onClick={() => toggleCollapseHtml(!isHtmlCollapsed)}
>
<CollapseIcon collapsed={isHtmlCollapsed} />
</button>
<pre {...props}>
<code>{htmlComponents}</code>
</pre>
Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,15 @@ 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 &&
Boolean(entry.originalCodeFrame) &&
Boolean(entry.originalStackFrame)
)

return {
firstFrame: error.frames[firstFirstPartyFrameIndex] ?? null,
}
return error.frames[firstFirstPartyFrameIndex] ?? null
}, [error.frames])

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,20 @@ export function CollapseIcon({ collapsed }: { collapsed?: boolean } = {}) {
<svg
data-nextjs-call-stack-chevron-icon
data-collapsed={collapsed}
width="16"
height="16"
fill="none"
height="20"
width="20"
shapeRendering="geometricPrecision"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
viewBox="0 0 24 24"
// rotate 90 degrees if not collapsed.
{...(typeof collapsed === 'boolean'
? { style: { transform: collapsed ? undefined : 'rotate(90deg)' } }
: {})}
>
<path d="M9 18l6-6-6-6" />
<path
fill="#666"
fillRule="evenodd"
d="m6.75 3.94.53.53 2.824 2.823a1 1 0 0 1 0 1.414L7.28 11.53l-.53.53L5.69 11l.53-.53L8.69 8 6.22 5.53 5.69 5l1.06-1.06Z"
clipRule="evenodd"
/>
</svg>
)
}
16 changes: 8 additions & 8 deletions test/development/acceptance-app/hydration-error.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(`
Expand Down Expand Up @@ -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:"`
)
})

Expand Down Expand Up @@ -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:"`
)
})

Expand Down Expand Up @@ -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:"`
)
})

Expand Down Expand Up @@ -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:"`
)
})

Expand All @@ -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()
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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:"`
)
})

Expand Down
14 changes: 7 additions & 7 deletions test/development/acceptance/hydration-error.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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:"`
)
}

Expand Down Expand Up @@ -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:"`
)
}
})
Expand Down Expand Up @@ -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:"`
)
}
})
Expand Down Expand Up @@ -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:"`
)
}
})
Expand Down Expand Up @@ -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:"`
)
}

Expand Down Expand Up @@ -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:"`
)
}

Expand Down Expand Up @@ -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:"`
)
}
})
Expand Down

0 comments on commit 46ace56

Please # to comment.