forked from vercel/next.js
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Ensure content is kept rendered below the error overlay on build erro…
…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
1 parent
caed5b5
commit 8859482
Showing
3 changed files
with
66 additions
and
82 deletions.
There are no files selected for viewing
33 changes: 0 additions & 33 deletions
33
packages/next/client/components/react-dev-overlay/internal/ErrorBoundary.tsx
This file was deleted.
Oops, something went wrong.
113 changes: 66 additions & 47 deletions
113
packages/next/client/components/react-dev-overlay/internal/ReactDevOverlay.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters