Skip to content

Commit 61777b8

Browse files
committed
[dev-overlay] Show error overlay on any thrown value in /app
1 parent f87fee7 commit 61777b8

File tree

5 files changed

+27
-18
lines changed

5 files changed

+27
-18
lines changed

.changeset/smooth-bears-run.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
'next': patch
3+
---
4+
5+
[dev-overlay] Show error overlay on any thrown value
6+
7+
We used to only show the error overlay on thrown values with a stack property.
8+
On other thrown values we kept the overlay collapsed.

packages/next/src/client/components/react-dev-overlay/app/app-dev-overlay-error-boundary.tsx

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,10 @@ import DefaultGlobalError, {
88
type AppDevOverlayErrorBoundaryProps = {
99
children: React.ReactNode
1010
globalError: [GlobalErrorComponent, React.ReactNode]
11-
onError: (value: boolean) => void
11+
onError: () => void
1212
}
1313

1414
type AppDevOverlayErrorBoundaryState = {
15-
isReactError: boolean
1615
reactError: unknown
1716
}
1817

@@ -43,33 +42,28 @@ export class AppDevOverlayErrorBoundary extends PureComponent<
4342
AppDevOverlayErrorBoundaryProps,
4443
AppDevOverlayErrorBoundaryState
4544
> {
46-
state = { isReactError: false, reactError: null }
45+
state = { reactError: null }
4746

4847
static getDerivedStateFromError(error: Error) {
49-
if (!error.stack) {
50-
return { isReactError: false, reactError: null }
51-
}
52-
5348
RuntimeErrorHandler.hadRuntimeError = true
5449

5550
return {
56-
isReactError: true,
5751
reactError: error,
5852
}
5953
}
6054

6155
componentDidCatch() {
62-
this.props.onError(this.state.isReactError)
56+
this.props.onError()
6357
}
6458

6559
render() {
6660
const { children, globalError } = this.props
67-
const { isReactError, reactError } = this.state
61+
const { reactError } = this.state
6862

6963
const fallback = (
7064
<ErroredHtml globalError={globalError} error={reactError} />
7165
)
7266

73-
return isReactError ? fallback : children
67+
return reactError !== null ? fallback : children
7468
}
7569
}

packages/next/src/client/components/react-dev-overlay/app/app-dev-overlay.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ export function AppDevOverlay({
8686
<>
8787
<AppDevOverlayErrorBoundary
8888
globalError={globalError}
89-
onError={setIsErrorOverlayOpen}
89+
onError={openOverlay}
9090
>
9191
<ReplaySsrOnlyErrors onBlockingError={openOverlay} />
9292
{children}

test/development/acceptance-app/hydration-error.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ describe('Error overlay for hydration errors in App router', () => {
210210
"componentStack": "...
211211
<HotReload assetPrefix="" globalError={[...]}>
212212
<AppDevOverlay state={{nextId:1, ...}} globalError={[...]}>
213-
<AppDevOverlayErrorBoundary globalError={[...]} onError={function bound dispatchSetState}>
213+
<AppDevOverlayErrorBoundary globalError={[...]} onError={function}>
214214
<ReplaySsrOnlyErrors>
215215
<DevRootHTTPAccessFallbackBoundary>
216216
<HTTPAccessFallbackBoundary notFound={<NotAllowedRootHTTPFallbackError>}>
@@ -246,7 +246,7 @@ describe('Error overlay for hydration errors in App router', () => {
246246
"componentStack": "...
247247
<HotReload assetPrefix="" globalError={[...]}>
248248
<AppDevOverlay state={{nextId:1, ...}} globalError={[...]}>
249-
<AppDevOverlayErrorBoundary globalError={[...]} onError={function bound dispatchSetState}>
249+
<AppDevOverlayErrorBoundary globalError={[...]} onError={function}>
250250
<ReplaySsrOnlyErrors>
251251
<DevRootHTTPAccessFallbackBoundary>
252252
<HTTPAccessFallbackBoundary notFound={<NotAllowedRootHTTPFallbackError>}>
@@ -1046,7 +1046,7 @@ describe('Error overlay for hydration errors in App router', () => {
10461046
"componentStack": "...
10471047
<HotReload assetPrefix="" globalError={[...]}>
10481048
<AppDevOverlay state={{nextId:1, ...}} globalError={[...]}>
1049-
<AppDevOverlayErrorBoundary globalError={[...]} onError={function bound dispatchSetState}>
1049+
<AppDevOverlayErrorBoundary globalError={[...]} onError={function}>
10501050
<ReplaySsrOnlyErrors>
10511051
<DevRootHTTPAccessFallbackBoundary>
10521052
<HTTPAccessFallbackBoundary notFound={<NotAllowedRootHTTPFallbackError>}>

test/development/app-dir/serialize-circular-error/serialize-circular-error.test.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,16 @@ describe('serialize-circular-error', () => {
2727
it('should serialize the object from client component in console correctly', async () => {
2828
const browser = await next.browser('/client')
2929

30-
// It's not a valid error object, it will display the global-error instead of the error overlay
31-
// TODO: handle the error object in the client-side
32-
await assertNoRedbox(browser)
30+
// TODO: Format arbitrary messages in Redbox
31+
await expect(browser).toDisplayRedbox(`
32+
{
33+
"description": "[object Object]",
34+
"environmentLabel": null,
35+
"label": "Runtime Error",
36+
"source": null,
37+
"stack": [],
38+
}
39+
`)
3340

3441
const bodyText = await browser.elementByCss('body').text()
3542
expect(bodyText).toContain(

0 commit comments

Comments
 (0)