diff --git a/packages/next/src/client/components/react-dev-overlay/app/app-dev-overlay.tsx b/packages/next/src/client/components/react-dev-overlay/app/app-dev-overlay.tsx
index bb1b74b51ea4..80110ed2b045 100644
--- a/packages/next/src/client/components/react-dev-overlay/app/app-dev-overlay.tsx
+++ b/packages/next/src/client/components/react-dev-overlay/app/app-dev-overlay.tsx
@@ -72,6 +72,11 @@ function ReplaySsrOnlyErrors({
return null
}
+function getSquashedHydrationErrorDetails() {
+ // We don't squash hydration errors in the App Router.
+ return null
+}
+
export function AppDevOverlay({
state,
dispatch,
@@ -99,7 +104,11 @@ export function AppDevOverlay({
<>
{/* Fonts can only be loaded outside the Shadow DOM. */}
-
+
>
>
)
diff --git a/packages/next/src/client/components/react-dev-overlay/pages/hydration-error-state.ts b/packages/next/src/client/components/react-dev-overlay/pages/hydration-error-state.ts
index 85919f946f08..1529529ce928 100644
--- a/packages/next/src/client/components/react-dev-overlay/pages/hydration-error-state.ts
+++ b/packages/next/src/client/components/react-dev-overlay/pages/hydration-error-state.ts
@@ -8,7 +8,7 @@ import {
isErrorMessageWithComponentStackDiff as isReact19HydrationWarning,
} from '../../react-19-hydration-error'
-type HydrationErrorState = {
+export type HydrationErrorState = {
// Hydration warning template format:
warning?: string
reactOutputComponentDiff?: string
diff --git a/packages/next/src/client/components/react-dev-overlay/pages/pages-dev-overlay.tsx b/packages/next/src/client/components/react-dev-overlay/pages/pages-dev-overlay.tsx
index f27060928a7d..5709bd316ad5 100644
--- a/packages/next/src/client/components/react-dev-overlay/pages/pages-dev-overlay.tsx
+++ b/packages/next/src/client/components/react-dev-overlay/pages/pages-dev-overlay.tsx
@@ -2,6 +2,7 @@ import { PagesDevOverlayErrorBoundary } from './pages-dev-overlay-error-boundary
import { usePagesDevOverlay } from './hooks'
import { FontStyles } from '../font/font-styles'
import { DevOverlay } from '../ui/dev-overlay'
+import { getSquashedHydrationErrorDetails } from './hydration-error-state'
export type ErrorType = 'runtime' | 'build'
@@ -22,7 +23,11 @@ export function PagesDevOverlay({ children }: PagesDevOverlayProps) {
{/* Fonts can only be loaded outside the Shadow DOM. */}
-
+
>
)
}
diff --git a/packages/next/src/client/components/react-dev-overlay/ui/components/errors/error-overlay/error-overlay.tsx b/packages/next/src/client/components/react-dev-overlay/ui/components/errors/error-overlay/error-overlay.tsx
index 150fc2820569..a6593902c3ca 100644
--- a/packages/next/src/client/components/react-dev-overlay/ui/components/errors/error-overlay/error-overlay.tsx
+++ b/packages/next/src/client/components/react-dev-overlay/ui/components/errors/error-overlay/error-overlay.tsx
@@ -9,6 +9,7 @@ import { BuildError } from '../../../container/build-error'
import { Errors } from '../../../container/errors'
import { useDelayedRender } from '../../../hooks/use-delayed-render'
import type { ReadyRuntimeError } from '../../../../utils/get-error-by-type'
+import type { HydrationErrorState } from '../../../../pages/hydration-error-state'
const transitionDurationMs = 200
@@ -23,11 +24,13 @@ export interface ErrorBaseProps {
export function ErrorOverlay({
state,
dispatch,
+ getSquashedHydrationErrorDetails,
runtimeErrors,
errorCount,
}: {
state: OverlayState
dispatch: OverlayDispatch
+ getSquashedHydrationErrorDetails: (error: Error) => HydrationErrorState | null
runtimeErrors: ReadyRuntimeError[]
errorCount: number
}) {
@@ -74,6 +77,7 @@ export function ErrorOverlay({
{
dispatch({ type: ACTION_ERROR_OVERLAY_CLOSE })
diff --git a/packages/next/src/client/components/react-dev-overlay/ui/container/errors.tsx b/packages/next/src/client/components/react-dev-overlay/ui/container/errors.tsx
index 3b8257e9b39d..70031ee92ab2 100644
--- a/packages/next/src/client/components/react-dev-overlay/ui/container/errors.tsx
+++ b/packages/next/src/client/components/react-dev-overlay/ui/container/errors.tsx
@@ -17,9 +17,10 @@ import {
} from '../../../react-19-hydration-error'
import type { ReadyRuntimeError } from '../../utils/get-error-by-type'
import type { ErrorBaseProps } from '../components/errors/error-overlay/error-overlay'
-import { getSquashedHydrationErrorDetails } from '../../pages/hydration-error-state'
+import type { HydrationErrorState } from '../../pages/hydration-error-state'
export interface ErrorsProps extends ErrorBaseProps {
+ getSquashedHydrationErrorDetails: (error: Error) => HydrationErrorState | null
runtimeErrors: ReadyRuntimeError[]
debugInfo: DebugInfo
onClose: () => void
@@ -72,7 +73,10 @@ const noErrorDetails = {
notes: null,
reactOutputComponentDiff: null,
}
-function useErrorDetails(error: Error | undefined): {
+function useErrorDetails(
+ error: Error | undefined,
+ getSquashedHydrationErrorDetails: (error: Error) => HydrationErrorState | null
+): {
hydrationWarning: string | null
notes: string | null
reactOutputComponentDiff: string | null
@@ -106,10 +110,11 @@ function useErrorDetails(error: Error | undefined): {
notes,
reactOutputComponentDiff: diff,
}
- }, [error])
+ }, [error, getSquashedHydrationErrorDetails])
}
export function Errors({
+ getSquashedHydrationErrorDetails,
runtimeErrors,
debugInfo,
onClose,
@@ -127,7 +132,10 @@ export function Errors({
() => runtimeErrors[activeIdx] ?? null,
[activeIdx, runtimeErrors]
)
- const errorDetails = useErrorDetails(activeError?.error)
+ const errorDetails = useErrorDetails(
+ activeError?.error,
+ getSquashedHydrationErrorDetails
+ )
if (isLoading) {
// TODO: better loading state
diff --git a/packages/next/src/client/components/react-dev-overlay/ui/dev-overlay.stories.tsx b/packages/next/src/client/components/react-dev-overlay/ui/dev-overlay.stories.tsx
index b3dababe5a51..ded4b633acf3 100644
--- a/packages/next/src/client/components/react-dev-overlay/ui/dev-overlay.stories.tsx
+++ b/packages/next/src/client/components/react-dev-overlay/ui/dev-overlay.stories.tsx
@@ -102,6 +102,10 @@ function useOverlayReducer() {
}, initialState)
}
+function getNoSquashedHydrationErrorDetails() {
+ return null
+}
+
export const Default: Story = {
render: function DevOverlayStory() {
const [state, dispatch] = useOverlayReducer()
@@ -115,7 +119,14 @@ export const Default: Story = {
objectFit: 'contain',
}}
/>
-
+
>
)
},
diff --git a/packages/next/src/client/components/react-dev-overlay/ui/dev-overlay.tsx b/packages/next/src/client/components/react-dev-overlay/ui/dev-overlay.tsx
index 1bde4b5e491c..d5304ccad2e4 100644
--- a/packages/next/src/client/components/react-dev-overlay/ui/dev-overlay.tsx
+++ b/packages/next/src/client/components/react-dev-overlay/ui/dev-overlay.tsx
@@ -10,13 +10,16 @@ import { DevToolsIndicator } from './components/errors/dev-tools-indicator/dev-t
import { RenderError } from './container/runtime-error/render-error'
import { DarkTheme } from './styles/dark-theme'
import { useDevToolsScale } from './components/errors/dev-tools-indicator/dev-tools-info/preferences'
+import type { HydrationErrorState } from '../pages/hydration-error-state'
export function DevOverlay({
state,
dispatch,
+ getSquashedHydrationErrorDetails,
}: {
state: OverlayState
dispatch: OverlayDispatch
+ getSquashedHydrationErrorDetails: (error: Error) => HydrationErrorState | null
}) {
const [scale, setScale] = useDevToolsScale()
return (
@@ -46,6 +49,9 @@ export function DevOverlay({