From 62c2f74b6b2000c0c8dffecdf133dc8b6ff3159b Mon Sep 17 00:00:00 2001 From: Jiwon Choi Date: Tue, 17 Dec 2024 20:35:53 +0900 Subject: [PATCH] Clean up `react-dev-overlay` before fork (#74016) Clean up `react-dev-overlay/` before forking for new UI. - Ported `pages/ReactDevOverlay/tsx` logic to a hook. - Moved `client-entry.tsx` to `app/` as it's only used in app router. Closes NDX-590 --- packages/next/src/client/app-index.tsx | 2 +- .../{ => app}/client-entry.tsx | 8 +-- .../pages/ReactDevOverlay.tsx | 49 ++++------------- .../react-dev-overlay/pages/hooks.ts | 53 +++++++++++++++++++ 4 files changed, 68 insertions(+), 44 deletions(-) rename packages/next/src/client/components/react-dev-overlay/{ => app}/client-entry.tsx (83%) create mode 100644 packages/next/src/client/components/react-dev-overlay/pages/hooks.ts diff --git a/packages/next/src/client/app-index.tsx b/packages/next/src/client/app-index.tsx index 65222c9aff7bf..58d3dd91a359e 100644 --- a/packages/next/src/client/app-index.tsx +++ b/packages/next/src/client/app-index.tsx @@ -250,7 +250,7 @@ export function hydrate() { shouldRenderRootLevelErrorOverlay() ) { const { createRootLevelDevOverlayElement } = - require('./components/react-dev-overlay/client-entry') as typeof import('./components/react-dev-overlay/client-entry') + require('./components/react-dev-overlay/app/client-entry') as typeof import('./components/react-dev-overlay/app/client-entry') // Note this won't cause hydration mismatch because we are doing CSR w/o hydration element = createRootLevelDevOverlayElement(element) diff --git a/packages/next/src/client/components/react-dev-overlay/client-entry.tsx b/packages/next/src/client/components/react-dev-overlay/app/client-entry.tsx similarity index 83% rename from packages/next/src/client/components/react-dev-overlay/client-entry.tsx rename to packages/next/src/client/components/react-dev-overlay/app/client-entry.tsx index 0427749681741..f728756be05e0 100644 --- a/packages/next/src/client/components/react-dev-overlay/client-entry.tsx +++ b/packages/next/src/client/components/react-dev-overlay/app/client-entry.tsx @@ -1,8 +1,8 @@ import React from 'react' -import ReactDevOverlay from './app/ReactDevOverlay' -import { getSocketUrl } from './internal/helpers/get-socket-url' -import { INITIAL_OVERLAY_STATE } from './shared' -import { HMR_ACTIONS_SENT_TO_BROWSER } from '../../../server/dev/hot-reloader-types' +import ReactDevOverlay from './ReactDevOverlay' +import { getSocketUrl } from '../internal/helpers/get-socket-url' +import { INITIAL_OVERLAY_STATE } from '../shared' +import { HMR_ACTIONS_SENT_TO_BROWSER } from '../../../../server/dev/hot-reloader-types' // if an error is thrown while rendering an RSC stream, this will catch it in dev // and show the error overlay diff --git a/packages/next/src/client/components/react-dev-overlay/pages/ReactDevOverlay.tsx b/packages/next/src/client/components/react-dev-overlay/pages/ReactDevOverlay.tsx index ba7548ea28396..104a70a8136e5 100644 --- a/packages/next/src/client/components/react-dev-overlay/pages/ReactDevOverlay.tsx +++ b/packages/next/src/client/components/react-dev-overlay/pages/ReactDevOverlay.tsx @@ -1,6 +1,5 @@ import * as React from 'react' -import * as Bus from './bus' import { ShadowPortal } from '../internal/components/ShadowPortal' import { BuildError } from '../internal/container/BuildError' import { Errors } from '../internal/container/Errors' @@ -8,19 +7,9 @@ import { ErrorBoundary } from './ErrorBoundary' import { Base } from '../internal/styles/Base' import { ComponentStyles } from '../internal/styles/ComponentStyles' import { CssReset } from '../internal/styles/CssReset' -import { useErrorOverlayReducer } from '../shared' +import { usePagesReactDevOverlay } from './hooks' -type ErrorType = 'runtime' | 'build' - -const shouldPreventDisplay = ( - errorType?: ErrorType | null, - preventType?: ErrorType[] | null -) => { - if (!preventType || !errorType) { - return false - } - return preventType.includes(errorType) -} +export type ErrorType = 'runtime' | 'build' interface ReactDevOverlayProps { children?: React.ReactNode @@ -33,32 +22,14 @@ export default function ReactDevOverlay({ preventDisplay, globalOverlay, }: ReactDevOverlayProps) { - const [state, dispatch] = useErrorOverlayReducer() - - React.useEffect(() => { - Bus.on(dispatch) - return function () { - Bus.off(dispatch) - } - }, [dispatch]) - - const onComponentError = React.useCallback( - (_error: Error, _componentStack: string | null) => { - // TODO: special handling - }, - [] - ) - - const hasBuildError = state.buildError != null - const hasRuntimeErrors = Boolean(state.errors.length) - const errorType = hasBuildError - ? 'build' - : hasRuntimeErrors - ? 'runtime' - : null - const isMounted = errorType !== null - - const displayPrevented = shouldPreventDisplay(errorType, preventDisplay) + const { + isMounted, + displayPrevented, + hasBuildError, + hasRuntimeErrors, + state, + onComponentError, + } = usePagesReactDevOverlay(preventDisplay) return ( <> diff --git a/packages/next/src/client/components/react-dev-overlay/pages/hooks.ts b/packages/next/src/client/components/react-dev-overlay/pages/hooks.ts new file mode 100644 index 0000000000000..acf3c0704a82c --- /dev/null +++ b/packages/next/src/client/components/react-dev-overlay/pages/hooks.ts @@ -0,0 +1,53 @@ +import type { ErrorType } from './ReactDevOverlay' +import React from 'react' +import * as Bus from './bus' +import { useErrorOverlayReducer } from '../shared' + +const shouldPreventDisplay = ( + errorType?: ErrorType | null, + preventType?: ErrorType[] | null +) => { + if (!preventType || !errorType) { + return false + } + return preventType.includes(errorType) +} + +export const usePagesReactDevOverlay = ( + preventDisplay: ErrorType[] | undefined +) => { + const [state, dispatch] = useErrorOverlayReducer() + + React.useEffect(() => { + Bus.on(dispatch) + return function () { + Bus.off(dispatch) + } + }, [dispatch]) + + const onComponentError = React.useCallback( + (_error: Error, _componentStack: string | null) => { + // TODO: special handling + }, + [] + ) + + const hasBuildError = state.buildError != null + const hasRuntimeErrors = Boolean(state.errors.length) + const errorType = hasBuildError + ? 'build' + : hasRuntimeErrors + ? 'runtime' + : null + const isMounted = errorType !== null + + const displayPrevented = shouldPreventDisplay(errorType, preventDisplay) + return { + isMounted, + displayPrevented, + hasBuildError, + hasRuntimeErrors, + state, + onComponentError, + } +}