diff --git a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/errors/error-overlay-floating-header/error-overlay-floating-header.stories.tsx b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/errors/error-overlay-floating-header/error-overlay-floating-header.stories.tsx
index 721bfd05b935c1..68fc4a8a94d512 100644
--- a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/errors/error-overlay-floating-header/error-overlay-floating-header.stories.tsx
+++ b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/errors/error-overlay-floating-header/error-overlay-floating-header.stories.tsx
@@ -20,19 +20,19 @@ export const Default: Story = {
id: 0,
runtime: true,
error: new Error('First error message'),
- frames: [],
+ frames: () => Promise.resolve([]),
},
{
id: 1,
runtime: true,
error: new Error('Second error message'),
- frames: [],
+ frames: () => Promise.resolve([]),
},
{
id: 2,
runtime: true,
error: new Error('Third error message'),
- frames: [],
+ frames: () => Promise.resolve([]),
},
],
activeIdx: 1,
diff --git a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/errors/error-overlay-pagination/error-overlay-pagination.stories.tsx b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/errors/error-overlay-pagination/error-overlay-pagination.stories.tsx
index 461f8c7b09fbc6..ecd85a925089fb 100644
--- a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/errors/error-overlay-pagination/error-overlay-pagination.stories.tsx
+++ b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/errors/error-overlay-pagination/error-overlay-pagination.stories.tsx
@@ -20,19 +20,19 @@ const mockErrors = [
id: 1,
runtime: true as const,
error: new Error('First error'),
- frames: [],
+ frames: () => Promise.resolve([]),
},
{
id: 2,
runtime: true as const,
error: new Error('Second error'),
- frames: [],
+ frames: () => Promise.resolve([]),
},
{
id: 3,
runtime: true as const,
error: new Error('Third error'),
- frames: [],
+ frames: () => Promise.resolve([]),
},
]
diff --git a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/container/errors.stories.tsx b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/container/errors.stories.tsx
index 148151d9086a94..47c756793617d1 100644
--- a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/container/errors.stories.tsx
+++ b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/container/errors.stories.tsx
@@ -74,74 +74,78 @@ const readyErrors: ReadyRuntimeError[] = [
id: 1,
runtime: true,
error: new Error('First error message'),
- frames: [
- frame,
- {
- ...frame,
- originalStackFrame: {
- ...frame.originalStackFrame,
- methodName: 'ParentComponent',
- lineNumber: 5,
+ frames: () =>
+ Promise.resolve([
+ frame,
+ {
+ ...frame,
+ originalStackFrame: {
+ ...frame.originalStackFrame,
+ methodName: 'ParentComponent',
+ lineNumber: 5,
+ },
},
- },
- {
- ...frame,
- originalStackFrame: {
- ...frame.originalStackFrame,
- methodName: 'GrandparentComponent',
- lineNumber: 1,
+ {
+ ...frame,
+ originalStackFrame: {
+ ...frame.originalStackFrame,
+ methodName: 'GrandparentComponent',
+ lineNumber: 1,
+ },
},
- },
- ...Array(20).fill(ignoredFrame),
- ],
+ ...Array(20).fill(ignoredFrame),
+ ]),
},
{
id: 2,
runtime: true,
error: new Error('Second error message'),
- frames: [
- {
- error: true,
- reason: 'Second error message',
- external: false,
- ignored: false,
- sourceStackFrame,
- originalStackFrame,
- originalCodeFrame: originalCodeFrame('Second error message'),
- },
- ],
+ frames: () =>
+ Promise.resolve([
+ {
+ error: true,
+ reason: 'Second error message',
+ external: false,
+ ignored: false,
+ sourceStackFrame,
+ originalStackFrame,
+ originalCodeFrame: originalCodeFrame('Second error message'),
+ },
+ ]),
},
{
id: 3,
runtime: true,
error: new Error('Third error message'),
- frames: [
- {
- error: true,
- reason: 'Third error message',
- external: false,
- ignored: false,
- sourceStackFrame,
- originalStackFrame,
- originalCodeFrame: originalCodeFrame('Third error message'),
- },
- ],
+ frames: () =>
+ Promise.resolve([
+ {
+ error: true,
+ reason: 'Third error message',
+ external: false,
+ ignored: false,
+ sourceStackFrame,
+ originalStackFrame,
+ originalCodeFrame: originalCodeFrame('Third error message'),
+ },
+ ]),
},
{
id: 4,
runtime: true,
error: new Error('Fourth error message'),
- frames: [
- {
- error: true,
- reason: 'Fourth error message',
- external: false,
- ignored: false,
- sourceStackFrame,
- originalStackFrame,
- originalCodeFrame: originalCodeFrame('Fourth error message'),
- },
- ],
+ frames: () =>
+ Promise.resolve([
+ {
+ error: true,
+ reason: 'Fourth error message',
+ external: false,
+ ignored: false,
+ sourceStackFrame,
+ originalStackFrame,
+ originalCodeFrame: originalCodeFrame('Fourth error message'),
+ },
+ ]),
},
]
@@ -205,21 +209,22 @@ export const WithHydrationWarning: Story = {
},
],
}),
- frames: [
- {
- error: true,
- reason: 'First error message',
- external: false,
- ignored: false,
- sourceStackFrame: {
- file: 'app/page.tsx',
- methodName: 'Home',
- arguments: [],
- lineNumber: 10,
- column: 5,
+ frames: () =>
+ Promise.resolve([
+ {
+ error: true,
+ reason: 'First error message',
+ external: false,
+ ignored: false,
+ sourceStackFrame: {
+ file: 'app/page.tsx',
+ methodName: 'Home',
+ arguments: [],
+ lineNumber: 10,
+ column: 5,
+ },
},
- },
- ],
+ ]),
},
],
debugInfo: { devtoolsFrontendUrl: undefined },
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 b57125e2a49ffd..bb3f75810a0ee3 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
@@ -1,4 +1,4 @@
-import { useState, useMemo, useEffect, useRef } from 'react'
+import { useState, useMemo, useEffect, useRef, Suspense } from 'react'
import type { DebugInfo } from '../../../types'
import { Overlay } from '../components/overlay'
import { noop as css } from '../helpers/noop-template'
@@ -192,11 +192,13 @@ export function Errors({
reactOutputComponentDiff={errorDetails.reactOutputComponentDiff}
/>
) : null}
-
+
+
+
)
}
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 78365ae924ad79..9366660a60cd54 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
@@ -1,4 +1,4 @@
-import { useMemo } from 'react'
+import { use, useMemo } from 'react'
import { CodeFrame } from '../../components/code-frame/code-frame'
import { CallStack } from '../../components/errors/call-stack/call-stack'
import { noop as css } from '../../helpers/noop-template'
@@ -11,16 +11,18 @@ export type RuntimeErrorProps = {
}
export function RuntimeError({ error, dialogResizerRef }: RuntimeErrorProps) {
+ const frames = use(error.frames())
+
const firstFrame = useMemo(() => {
- const firstFirstPartyFrameIndex = error.frames.findIndex(
+ const firstFirstPartyFrameIndex = frames.findIndex(
(entry) =>
!entry.ignored &&
Boolean(entry.originalCodeFrame) &&
Boolean(entry.originalStackFrame)
)
- return error.frames[firstFirstPartyFrameIndex] ?? null
- }, [error.frames])
+ return frames[firstFirstPartyFrameIndex] ?? null
+ }, [frames])
return (
<>
@@ -32,7 +34,7 @@ export function RuntimeError({ error, dialogResizerRef }: RuntimeErrorProps) {
)}
{error.frames.length > 0 && (
-
+
)}
>
)
diff --git a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/container/runtime-error/use-error-hook.ts b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/container/runtime-error/use-error-hook.ts
index 3b0fb084bfb18a..52f659946446a5 100644
--- a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/container/runtime-error/use-error-hook.ts
+++ b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/container/runtime-error/use-error-hook.ts
@@ -81,25 +81,13 @@ export function useErrorHook({
if (nextError == null) {
return
}
- let mounted = true
- getErrorByType(nextError, isAppDir).then(
- (resolved) => {
- // We don't care if the desired error changed while we were resolving,
- // thus we're not tracking it using a ref. Once the work has been done,
- // we'll store it.
- if (mounted) {
- setLookups((m) => ({ ...m, [resolved.id]: resolved }))
- }
- },
- () => {
- // TODO: handle this, though an edge case
- }
- )
+ const resolved = getErrorByType(nextError, isAppDir)
- return () => {
- mounted = false
- }
+ // We don't care if the desired error changed while we were resolving,
+ // thus we're not tracking it using a ref. Once the work has been done,
+ // we'll store it.
+ setLookups((m) => ({ ...m, [resolved.id]: resolved }))
}, [nextError, isAppDir])
return {
diff --git a/packages/next/src/client/components/react-dev-overlay/internal/container/Errors.tsx b/packages/next/src/client/components/react-dev-overlay/internal/container/Errors.tsx
index c46ac62bc2198c..3c3026072bef38 100644
--- a/packages/next/src/client/components/react-dev-overlay/internal/container/Errors.tsx
+++ b/packages/next/src/client/components/react-dev-overlay/internal/container/Errors.tsx
@@ -1,4 +1,4 @@
-import { useState, useEffect, useMemo, useCallback } from 'react'
+import { useState, useEffect, useMemo, useCallback, Suspense } from 'react'
import {
ACTION_UNHANDLED_ERROR,
ACTION_UNHANDLED_REJECTION,
@@ -162,25 +162,13 @@ export function Errors({
if (nextError == null) {
return
}
- let mounted = true
-
- getErrorByType(nextError, isAppDir).then(
- (resolved) => {
- // We don't care if the desired error changed while we were resolving,
- // thus we're not tracking it using a ref. Once the work has been done,
- // we'll store it.
- if (mounted) {
- setLookups((m) => ({ ...m, [resolved.id]: resolved }))
- }
- },
- () => {
- // TODO: handle this, though an edge case
- }
- )
- return () => {
- mounted = false
- }
+ const resolved = getErrorByType(nextError, isAppDir)
+
+ // We don't care if the desired error changed while we were resolving,
+ // thus we're not tracking it using a ref. Once the work has been done,
+ // we'll store it.
+ setLookups((m) => ({ ...m, [resolved.id]: resolved }))
}, [nextError, isAppDir])
const [displayState, setDisplayState] =
@@ -399,9 +387,14 @@ export function Errors({
) : undefined}
-
-
-
+
+
+
+
+
diff --git a/packages/next/src/client/components/react-dev-overlay/internal/container/RuntimeError/index.tsx b/packages/next/src/client/components/react-dev-overlay/internal/container/RuntimeError/index.tsx
index cb4b88b5bd1ff9..764faa04cd5a27 100644
--- a/packages/next/src/client/components/react-dev-overlay/internal/container/RuntimeError/index.tsx
+++ b/packages/next/src/client/components/react-dev-overlay/internal/container/RuntimeError/index.tsx
@@ -3,18 +3,21 @@ import { CodeFrame } from '../../components/CodeFrame'
import type { ReadyRuntimeError } from '../../helpers/get-error-by-type'
import { noop as css } from '../../helpers/noop-template'
import { CallStackFrame } from './CallStackFrame'
+import { use } from 'react'
export type RuntimeErrorProps = { error: ReadyRuntimeError }
export function RuntimeError({ error }: RuntimeErrorProps) {
const [isIgnoredExpanded, setIsIgnoredExpanded] = React.useState(false)
+
+ const frames = use(error.frames())
const {
firstFrame,
allLeadingFrames,
trailingCallStackFrames,
displayedFramesCount,
} = React.useMemo(() => {
- const filteredFrames = error.frames.filter((frame) =>
+ const filteredFrames = frames.filter((frame) =>
isIgnoredExpanded ? true : !frame.ignored
)
@@ -36,7 +39,7 @@ export function RuntimeError({ error }: RuntimeErrorProps) {
firstFirstPartyFrameIndex < 0 ? 0 : firstFirstPartyFrameIndex
),
}
- }, [error.frames, isIgnoredExpanded])
+ }, [frames, isIgnoredExpanded])
return (
@@ -64,8 +67,7 @@ export function RuntimeError({ error }: RuntimeErrorProps) {
))}
{
// if the default displayed ignored frames count is equal equal to the total frames count, hide the button
- displayedFramesCount === error.frames.length &&
- !isIgnoredExpanded ? null : (
+ displayedFramesCount === frames.length && !isIgnoredExpanded ? null : (