1
- import { useState , useMemo , useRef , Suspense } from 'react'
1
+ import { useMemo , useRef , Suspense } from 'react'
2
2
import type { DebugInfo } from '../../shared/types'
3
3
import { Overlay , OverlayBackdrop } from '../components/overlay'
4
4
import { RuntimeError } from './runtime-error'
5
5
import { getErrorSource } from '../../../shared/lib/error-source'
6
6
import { HotlinkedText } from '../components/hot-linked-text'
7
7
import { PseudoHtmlDiff } from './runtime-error/component-stack-pseudo-html'
8
- import { extractNextErrorCode } from '../../../lib/error-telemetry-utils'
9
8
import {
10
9
ErrorOverlayLayout ,
11
10
type ErrorOverlayLayoutProps ,
@@ -18,6 +17,7 @@ import {
18
17
import type { ReadyRuntimeError } from '../utils/get-error-by-type'
19
18
import type { ErrorBaseProps } from '../components/errors/error-overlay/error-overlay'
20
19
import type { HydrationErrorState } from '../../shared/hydration-error'
20
+ import { useRuntimeError } from '../hooks/use-runtime-error'
21
21
22
22
export interface ErrorsProps extends ErrorBaseProps {
23
23
getSquashedHydrationErrorDetails : ( error : Error ) => HydrationErrorState | null
@@ -26,8 +26,6 @@ export interface ErrorsProps extends ErrorBaseProps {
26
26
onClose : ( ) => void
27
27
}
28
28
29
- type ReadyErrorEvent = ReadyRuntimeError
30
-
31
29
function isNextjsLink ( text : string ) : boolean {
32
30
return text . startsWith ( 'https://nextjs.org' )
33
31
}
@@ -55,7 +53,7 @@ function GenericErrorDescription({ error }: { error: Error }) {
55
53
)
56
54
}
57
55
58
- function getErrorTypeLabel (
56
+ export function getErrorTypeLabel (
59
57
error : Error ,
60
58
type : ReadyRuntimeError [ 'type' ]
61
59
) : ErrorOverlayLayoutProps [ 'errorType' ] {
@@ -73,7 +71,7 @@ const noErrorDetails = {
73
71
notes : null ,
74
72
reactOutputComponentDiff : null ,
75
73
}
76
- function useErrorDetails (
74
+ export function useErrorDetails (
77
75
error : Error | undefined ,
78
76
getSquashedHydrationErrorDetails : ( error : Error ) => HydrationErrorState | null
79
77
) : {
@@ -122,20 +120,17 @@ export function Errors({
122
120
} : ErrorsProps ) {
123
121
const dialogResizerRef = useRef < HTMLDivElement | null > ( null )
124
122
125
- const isLoading = useMemo < boolean > ( ( ) => {
126
- return runtimeErrors . length < 1
127
- } , [ runtimeErrors . length ] )
128
-
129
- const [ activeIdx , setActiveIndex ] = useState < number > ( 0 )
130
-
131
- const activeError = useMemo < ReadyErrorEvent | null > (
132
- ( ) => runtimeErrors [ activeIdx ] ?? null ,
133
- [ activeIdx , runtimeErrors ]
134
- )
135
- const errorDetails = useErrorDetails (
136
- activeError ?. error ,
137
- getSquashedHydrationErrorDetails
138
- )
123
+ const {
124
+ isLoading,
125
+ errorCode,
126
+ errorType,
127
+ notes,
128
+ hydrationWarning,
129
+ activeIdx,
130
+ errorDetails,
131
+ activeError,
132
+ setActiveIndex,
133
+ } = useRuntimeError ( { runtimeErrors, getSquashedHydrationErrorDetails } )
139
134
140
135
if ( isLoading ) {
141
136
// TODO: better loading state
@@ -154,12 +149,6 @@ export function Errors({
154
149
const isServerError = [ 'server' , 'edge-server' ] . includes (
155
150
getErrorSource ( error ) || ''
156
151
)
157
- const errorType = getErrorTypeLabel ( error , activeError . type )
158
- // TOOD: May be better to always treat everything past the first blank line as notes
159
- // We're currently only special casing hydration error messages.
160
- const notes = errorDetails . notes
161
- const hydrationWarning = errorDetails . hydrationWarning
162
- const errorCode = extractNextErrorCode ( error )
163
152
164
153
return (
165
154
< ErrorOverlayLayout
0 commit comments