Skip to content

Commit

Permalink
Don't show error overlay for not found and redirect (#41438)
Browse files Browse the repository at this point in the history
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
  • Loading branch information
timneutkens and kodiakhq[bot] committed Oct 15, 2022
1 parent 59eefb2 commit 1b84782
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 28 deletions.
27 changes: 15 additions & 12 deletions packages/next/client/components/layout-router.tsx
Expand Up @@ -278,9 +278,13 @@ interface RedirectBoundaryProps {
children: React.ReactNode
}

function InfinitePromiseComponent() {
use(createInfinitePromise())
return <></>
function HandleRedirect({ redirect }: { redirect: string }) {
const router = useContext(AppRouterContext)

useEffect(() => {
router.replace(redirect, {})
}, [redirect, router])
return null
}

class RedirectErrorBoundary extends React.Component<
Expand All @@ -297,20 +301,14 @@ class RedirectErrorBoundary extends React.Component<
const url = error.digest.split(';')[1]
return { redirect: url }
}
// Re-throw if error is not for 404
// Re-throw if error is not for redirect
throw error
}

render() {
const redirect = this.state.redirect
if (redirect !== null) {
setTimeout(() => {
// @ts-ignore startTransition exists
React.startTransition(() => {
this.props.router.replace(redirect, {})
})
})
return <InfinitePromiseComponent />
return <HandleRedirect redirect={redirect} />
}

return this.props.children
Expand Down Expand Up @@ -348,7 +346,12 @@ class NotFoundErrorBoundary extends React.Component<

render() {
if (this.state.notFoundTriggered) {
return this.props.notFound
return (
<>
<meta name="robots" content="noindex" />
{this.props.notFound}
</>
)
}

return this.props.children
Expand Down
10 changes: 10 additions & 0 deletions packages/next/client/components/react-dev-overlay/hot-reloader.tsx
Expand Up @@ -445,6 +445,16 @@ export default function HotReload({
})

const handleOnUnhandledError = useCallback((ev) => {
if (
ev.error &&
ev.error.digest &&
(ev.error.digest.startsWith('NEXT_REDIRECT') ||
ev.error.digest === 'NEXT_NOT_FOUND')
) {
ev.preventDefault()
return
}

hadRuntimeError = true
onUnhandledError(dispatch, ev)
}, [])
Expand Down
45 changes: 29 additions & 16 deletions test/e2e/app-dir/index.test.ts
Expand Up @@ -1693,40 +1693,52 @@ describe('app dir', () => {
expect(
await browser.waitForElementByCss('#not-found-component').text()
).toBe('Not Found!')
expect(
await browser
.waitForElementByCss('meta[name="robots"]')
.getAttribute('content')
).toBe('noindex')
})

it.skip('should trigger not-found in a client component', async () => {
it('should trigger not-found in a client component', async () => {
const browser = await webdriver(next.url, '/not-found/clientcomponent')
expect(
await browser.waitForElementByCss('#not-found-component').text()
).toBe('Not Found!')
expect(
await browser
.waitForElementByCss('meta[name="robots"]')
.getAttribute('content')
).toBe('noindex')
})
;(isDev ? it.skip : it)(
'should trigger not-found client-side',
async () => {
const browser = await webdriver(next.url, '/not-found/client-side')
it('should trigger not-found client-side', async () => {
const browser = await webdriver(next.url, '/not-found/client-side')
await browser
.elementByCss('button')
.click()
.waitForElementByCss('#not-found-component')
expect(await browser.elementByCss('#not-found-component').text()).toBe(
'Not Found!'
)
expect(
await browser
.elementByCss('button')
.click()
.waitForElementByCss('#not-found-component')
expect(
await browser.elementByCss('#not-found-component').text()
).toBe('Not Found!')
}
)
.waitForElementByCss('meta[name="robots"]')
.getAttribute('content')
).toBe('noindex')
})
})

describe('redirect', () => {
describe('components', () => {
it.skip('should redirect in a server component', async () => {
it('should redirect in a server component', async () => {
const browser = await webdriver(next.url, '/redirect/servercomponent')
await browser.waitForElementByCss('#result-page')
expect(await browser.elementByCss('#result-page').text()).toBe(
'Result Page'
)
})

it.skip('should redirect in a client component', async () => {
it('should redirect in a client component', async () => {
const browser = await webdriver(next.url, '/redirect/clientcomponent')
await browser.waitForElementByCss('#result-page')
expect(await browser.elementByCss('#result-page').text()).toBe(
Expand All @@ -1735,12 +1747,13 @@ describe('app dir', () => {
})

// TODO-APP: Enable in development
;(isDev ? it.skip : it)('should redirect client-side', async () => {
it('should redirect client-side', async () => {
const browser = await webdriver(next.url, '/redirect/client-side')
await browser
.elementByCss('button')
.click()
.waitForElementByCss('#result-page')
// eslint-disable-next-line jest/no-standalone-expect
expect(await browser.elementByCss('#result-page').text()).toBe(
'Result Page'
)
Expand Down

0 comments on commit 1b84782

Please sign in to comment.