Fix global-error for nested routes (#60539)
## What This fixes when the deep nested routes throws a client side error, it can still be caught by the `global-error.js` ## How We should always resolve global-error from root app directory instead of current route's layout. Also fixed a bad test before where the gloabl-error.js is not located correctly Fixes #53756 Closes NEXT-1760
This commit is contained in:
parent
e07161a563
commit
98b99e408b
6 changed files with 47 additions and 10 deletions
|
@ -198,7 +198,7 @@ async function createTreeCodeFromPath(
|
|||
const pages: string[] = []
|
||||
|
||||
let rootLayout: string | undefined
|
||||
let globalError: string = defaultGlobalErrorPath
|
||||
let globalError: string | undefined
|
||||
|
||||
async function resolveAdjacentParallelSegments(
|
||||
segmentPath: string
|
||||
|
@ -356,20 +356,20 @@ async function createTreeCodeFromPath(
|
|||
)?.[1]
|
||||
rootLayout = layoutPath
|
||||
|
||||
if (isDefaultNotFound && !layoutPath) {
|
||||
if (isDefaultNotFound && !layoutPath && !rootLayout) {
|
||||
rootLayout = defaultLayoutPath
|
||||
definedFilePaths.push(['layout', rootLayout])
|
||||
}
|
||||
}
|
||||
|
||||
if (layoutPath) {
|
||||
if (!globalError) {
|
||||
const resolvedGlobalErrorPath = await resolver(
|
||||
`${path.dirname(layoutPath)}/${GLOBAL_ERROR_FILE_TYPE}`
|
||||
`${appDirPrefix}/${GLOBAL_ERROR_FILE_TYPE}`
|
||||
)
|
||||
if (resolvedGlobalErrorPath) {
|
||||
globalError = resolvedGlobalErrorPath
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let parallelSegmentKey = Array.isArray(parallelSegment)
|
||||
? parallelSegment[0]
|
||||
|
@ -468,7 +468,7 @@ async function createTreeCodeFromPath(
|
|||
treeCode: `${treeCode}.children;`,
|
||||
pages: `${JSON.stringify(pages)};`,
|
||||
rootLayout,
|
||||
globalError,
|
||||
globalError: globalError ?? defaultGlobalErrorPath,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,3 +12,6 @@ export default function GlobalError({ error }) {
|
|||
</html>
|
||||
)
|
||||
}
|
||||
|
||||
// for inspecting purpose
|
||||
GlobalError.displayName = 'GlobalError'
|
||||
|
|
3
test/e2e/app-dir/global-error/basic/app/nested/layout.js
Normal file
3
test/e2e/app-dir/global-error/basic/app/nested/layout.js
Normal file
|
@ -0,0 +1,3 @@
|
|||
export default function NestedLayout({ children }) {
|
||||
return <div>{children}</div>
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
'use client'
|
||||
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
export default function ClientPage() {
|
||||
const [bad, setBad] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
setTimeout(() => {
|
||||
setBad(true)
|
||||
})
|
||||
}, [])
|
||||
|
||||
if (bad) {
|
||||
throw Error('nested error')
|
||||
}
|
||||
|
||||
return <p>client page</p>
|
||||
}
|
|
@ -79,5 +79,17 @@ createNextDescribe(
|
|||
)
|
||||
}
|
||||
})
|
||||
|
||||
it('should catch the client error thrown in the nested routes', async () => {
|
||||
const browser = await next.browser('/nested/nested')
|
||||
if (isNextDev) {
|
||||
await testDev(browser, /Error: nested error/)
|
||||
} else {
|
||||
expect(await browser.elementByCss('h1').text()).toBe('Global Error')
|
||||
expect(await browser.elementByCss('#error').text()).toBe(
|
||||
'Global error: nested error'
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue