Skip to content

Commit

Permalink
Ensure content is kept rendered below the error overlay on build erro…
Browse files Browse the repository at this point in the history
…rs in new router (vercel#41360)

- Remove unused code
- Keep rendering underlying component tree when there is a build error
- Move error catch up one level



## Bug

- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Errors have a helpful link attached, see `contributing.md`

## Feature

- [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR.
- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Documentation added
- [ ] Telemetry added. In case of a feature if it's used or not.
- [ ] Errors have a helpful link attached, see `contributing.md`

## Documentation / Examples

- [ ] Make sure the linting passes by running `pnpm lint`
- [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)
  • Loading branch information
timneutkens authored and Kikobeats committed Oct 24, 2022
1 parent caed5b5 commit 8859482
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 82 deletions.

This file was deleted.

@@ -1,61 +1,80 @@
import * as React from 'react'
import type { OverlayState } from './error-overlay-reducer'
import {
ACTION_UNHANDLED_ERROR,
OverlayState,
UnhandledErrorAction,
} from './error-overlay-reducer'

import { ShadowPortal } from './components/ShadowPortal'
import { BuildError } from './container/BuildError'
import { Errors } from './container/Errors'
import { ErrorBoundary } from './ErrorBoundary'
import { Errors, SupportedErrorEvent } from './container/Errors'
import { Base } from './styles/Base'
import { ComponentStyles } from './styles/ComponentStyles'
import { CssReset } from './styles/CssReset'
import { parseStack } from './helpers/parseStack'

type ErrorType = 'runtime' | 'build'
interface ReactDevOverlayState {
reactError: SupportedErrorEvent | null
}
class ReactDevOverlay extends React.PureComponent<
{
state: OverlayState
children: React.ReactNode
},
ReactDevOverlayState
> {
state = { reactError: null }

const shouldPreventDisplay = (
errorType?: ErrorType | null,
preventType?: ErrorType[] | null
) => {
if (!preventType || !errorType) {
return false
static getDerivedStateFromError(error: Error): ReactDevOverlayState {
const e = error
const event: UnhandledErrorAction = {
type: ACTION_UNHANDLED_ERROR,
reason: error,
frames: parseStack(e.stack!),
}
const errorEvent: SupportedErrorEvent = {
id: 0,
event,
}
return { reactError: errorEvent }
}
return preventType.includes(errorType)
}

function ReactDevOverlay({
state,
children,
preventDisplay,
}: {
state: OverlayState
children?: React.ReactNode
preventDisplay?: ErrorType[]
}) {
const hasBuildError = state.buildError != null
const hasRuntimeErrors = Boolean(state.errors.length)

const isMounted = hasBuildError || hasRuntimeErrors

return (
<>
<ErrorBoundary isMounted={isMounted}>{children}</ErrorBoundary>
{isMounted ? (
<ShadowPortal>
<CssReset />
<Base />
<ComponentStyles />

{shouldPreventDisplay(
hasBuildError ? 'build' : hasRuntimeErrors ? 'runtime' : null,
preventDisplay
) ? null : hasBuildError ? (
<BuildError message={state.buildError!} />
) : hasRuntimeErrors ? (
<Errors errors={state.errors} />
) : undefined}
</ShadowPortal>
) : undefined}
</>
)
render() {
const { state, children } = this.props
const { reactError } = this.state

const hasBuildError = state.buildError != null
const hasRuntimeErrors = Boolean(state.errors.length)
const isMounted = hasBuildError || hasRuntimeErrors || reactError

return (
<>
{reactError ? (
<html>
<head></head>
<body></body>
</html>
) : (
children
)}
{isMounted ? (
<ShadowPortal>
<CssReset />
<Base />
<ComponentStyles />

{hasBuildError ? (
<BuildError message={state.buildError!} />
) : hasRuntimeErrors ? (
<Errors errors={state.errors} />
) : reactError ? (
<Errors errors={[reactError]} />
) : undefined}
</ShadowPortal>
) : undefined}
</>
)
}
}

export default ReactDevOverlay
Expand Up @@ -69,8 +69,6 @@ export function errorOverlayReducer(
}
}
default: {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const _: never = action
return state
}
}
Expand Down

0 comments on commit 8859482

Please sign in to comment.