From ce9c6ae45e9884e7d4726497b5a5c92f44cf439f Mon Sep 17 00:00:00 2001 From: eps1lon Date: Wed, 24 Apr 2024 19:07:43 +0200 Subject: [PATCH] Fix error overlay Fixes displaying 2 errors in the redbox when just one was thrown. It counted 2 because we had the actual error and React's "the above occured" --- .../internal/helpers/use-error-handler.ts | 40 +++++++++++++------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/packages/next/src/client/components/react-dev-overlay/internal/helpers/use-error-handler.ts b/packages/next/src/client/components/react-dev-overlay/internal/helpers/use-error-handler.ts index be00a7ccd94e5..803538143f859 100644 --- a/packages/next/src/client/components/react-dev-overlay/internal/helpers/use-error-handler.ts +++ b/packages/next/src/client/components/react-dev-overlay/internal/helpers/use-error-handler.ts @@ -19,16 +19,11 @@ const errorHandlers: Array = [] const rejectionHandlers: Array = [] if (typeof window !== 'undefined') { - // These event handlers must be added outside of the hook because there is no - // guarantee that the hook will be alive in a mounted component in time to - // when the errors occur. - window.addEventListener('error', (ev: WindowEventMap['error']): void => { - if (isNextRouterError(ev.error)) { - ev.preventDefault() - return + function handleError(error: unknown) { + if (isNextRouterError(error)) { + return false } - const error = ev?.error if ( !error || !(error instanceof Error) || @@ -60,18 +55,39 @@ if (typeof window !== 'undefined') { '\nSee more info here: https://nextjs.org/docs/messages/react-hydration-error' } - const e = error // Only queue one hydration every time if (isCausedByHydrationFailure) { if (!hasHydrationError) { - errorQueue.push(e) + errorQueue.push(error) } hasHydrationError = true } for (const handler of errorHandlers) { - handler(e) + handler(error) + } + } + // These event handlers must be added outside of the hook because there is no + // guarantee that the hook will be alive in a mounted component in time to + // when the errors occur. + // uncaught errors go through reportError + window.addEventListener( + 'error', + (event: WindowEventMap['error']): void | boolean => { + if (handleError(event.error) === false) { + event.preventDefault() + return false + } + } + ) + // caught errors go through console.error + const origConsoleError = window.console.error + window.console.error = (...args) => { + // See https://github.com/facebook/react/blob/d50323eb845c5fde0d720cae888bf35dedd05506/packages/react-reconciler/src/ReactFiberErrorLogger.js#L78 + const error = process.env.NODE_ENV !== 'production' ? args[1] : args[0] + if (handleError(error) !== false) { + origConsoleError.apply(window.console, args) } - }) + } window.addEventListener( 'unhandledrejection', (ev: WindowEventMap['unhandledrejection']): void => {