Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(react-dev-overlay): export getErrorByType and add preventDisplay prop #34237

Merged
merged 4 commits into from Feb 18, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/next/compiled/@next/react-dev-overlay/client.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions packages/react-dev-overlay/src/client.ts
Expand Up @@ -87,6 +87,7 @@ function onRefresh() {
Bus.emit({ type: Bus.TYPE_REFRESH })
}

export { getErrorByType } from './internal/helpers/getErrorByType'
export { getNodeError } from './internal/helpers/nodeStackFrames'
export { default as ReactDevOverlay } from './internal/ReactDevOverlay'
export {
Expand Down
28 changes: 27 additions & 1 deletion packages/react-dev-overlay/src/internal/ReactDevOverlay.tsx
Expand Up @@ -58,8 +58,14 @@ function reducer(state: OverlayState, ev: Bus.BusEvent): OverlayState {
}
}

type ErrorType = 'runtime' | 'build' | 'full-refresh'

const ReactDevOverlay: React.FunctionComponent = function ReactDevOverlay({
children,
preventDisplay,
}: {
children?: React.ReactNode
preventDisplay?: ErrorType[]
}) {
const [state, dispatch] = React.useReducer<
React.Reducer<OverlayState, Bus.BusEvent>
Expand Down Expand Up @@ -90,6 +96,7 @@ const ReactDevOverlay: React.FunctionComponent = function ReactDevOverlay({
const isAboutToFullRefresh = state.isAboutToFullRefresh

const isMounted = hasBuildError || hasRuntimeErrors || isAboutToFullRefresh

return (
<React.Fragment>
<ErrorBoundary onError={onComponentError}>
Expand All @@ -101,7 +108,16 @@ const ReactDevOverlay: React.FunctionComponent = function ReactDevOverlay({
<Base />
<ComponentStyles />

{hasBuildError ? (
{shouldPreventDisplay(
hasBuildError
? 'build'
: hasRuntimeErrors
? 'runtime'
: isAboutToFullRefresh
? 'full-refresh'
: null,
preventDisplay
) ? null : hasBuildError ? (
<BuildError message={state.buildError!} />
) : hasRuntimeErrors ? (
<Errors errors={state.errors} />
Expand All @@ -114,4 +130,14 @@ const ReactDevOverlay: React.FunctionComponent = function ReactDevOverlay({
)
}

const shouldPreventDisplay = (
errorType?: ErrorType | null,
preventType?: ErrorType[] | null
) => {
if (!preventType || !errorType) {
return false
}
return preventType.includes(errorType)
}

export default ReactDevOverlay
38 changes: 1 addition & 37 deletions packages/react-dev-overlay/src/internal/container/Errors.tsx
Expand Up @@ -14,12 +14,9 @@ import {
import { LeftRightDialogHeader } from '../components/LeftRightDialogHeader'
import { Overlay } from '../components/Overlay'
import { Toast } from '../components/Toast'
import { getErrorByType, ReadyRuntimeError } from '../helpers/getErrorByType'
import { isNodeError } from '../helpers/nodeStackFrames'
import { noop as css } from '../helpers/noop-template'
import {
getOriginalStackFrames,
OriginalStackFrame,
} from '../helpers/stack-frame'
import { RuntimeError } from './RuntimeError'

export type SupportedErrorEvent = {
Expand All @@ -28,13 +25,6 @@ export type SupportedErrorEvent = {
}
export type ErrorsProps = { errors: SupportedErrorEvent[] }

export type ReadyRuntimeError = {
id: number

runtime: true
error: Error
frames: OriginalStackFrame[]
}
type ReadyErrorEvent = ReadyRuntimeError

function getErrorSignature(ev: SupportedErrorEvent): string {
Expand Down Expand Up @@ -82,32 +72,6 @@ const HotlinkedText: React.FC<{
)
}

async function getErrorByType(
ev: SupportedErrorEvent
): Promise<ReadyErrorEvent> {
const { id, event } = ev
switch (event.type) {
case TYPE_UNHANDLED_ERROR:
case TYPE_UNHANDLED_REJECTION: {
return {
id,
runtime: true,
error: event.reason,
frames: await getOriginalStackFrames(
isNodeError(event.reason),
event.frames
),
}
}
default: {
break
}
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const _: never = event
throw new Error('type system invariant violation')
}

export const Errors: React.FC<ErrorsProps> = function Errors({ errors }) {
const [lookups, setLookups] = React.useState(
{} as { [eventId: string]: ReadyErrorEvent }
Expand Down
@@ -1,9 +1,9 @@
import * as React from 'react'
import { StackFrame } from 'stacktrace-parser'
import { CodeFrame } from '../components/CodeFrame'
import { ReadyRuntimeError } from '../helpers/getErrorByType'
import { noop as css } from '../helpers/noop-template'
import { getFrameSource, OriginalStackFrame } from '../helpers/stack-frame'
import { ReadyRuntimeError } from './Errors'

export type RuntimeErrorProps = { error: ReadyRuntimeError }

Expand Down
@@ -0,0 +1,37 @@
import { TYPE_UNHANDLED_ERROR, TYPE_UNHANDLED_REJECTION } from '../bus'
import { SupportedErrorEvent } from '../container/Errors'
import { isNodeError } from './nodeStackFrames'
import { getOriginalStackFrames, OriginalStackFrame } from './stack-frame'

export type ReadyRuntimeError = {
id: number
runtime: true
error: Error
frames: OriginalStackFrame[]
}

export async function getErrorByType(
ev: SupportedErrorEvent
): Promise<ReadyRuntimeError> {
const { id, event } = ev
switch (event.type) {
case TYPE_UNHANDLED_ERROR:
case TYPE_UNHANDLED_REJECTION: {
return {
id,
runtime: true,
error: event.reason,
frames: await getOriginalStackFrames(
isNodeError(event.reason),
event.frames
),
}
}
default: {
break
}
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const _: never = event
throw new Error('type system invariant violation')
}