mirror of
https://github.com/hanzoai/next.js.git
synced 2026-09-24 17:00:51 +00:00
our error boundaries had a bunch of logic that set `state.error = error`
and then checked `if (state.error)`, which only works correctly if
thrown value is truthy. it breaks if something does e.g. `throw
undefined`. in this case, we would incorrectly think that no error
occurred and render children again (instead of a fallback), which can
then lead to an infinite loop if the children throw again.
the fix is to wrap the thrown value, so `state.error` is either `null`
(initial/reset) or `{ thrownValue: ... }` if something errored. i
initially considered using a separate `state.hasError` boolean, but
that's a bit annoying to type, and really we want to model this as a
discriminated union, so using a pseudo-Optional thing is nicer.
20 lines
429 B
TypeScript
20 lines
429 B
TypeScript
import { Suspense } from 'react'
|
|
import { connection } from 'next/server'
|
|
import ErrorWrapper from './error-wrapper'
|
|
|
|
export default function Page() {
|
|
return (
|
|
<ErrorWrapper>
|
|
<Suspense>
|
|
<PageImpl />
|
|
</Suspense>
|
|
</ErrorWrapper>
|
|
)
|
|
}
|
|
|
|
async function PageImpl(): Promise<never> {
|
|
await connection()
|
|
// eslint-disable-next-line no-throw-literal -- testing bad values on purpose
|
|
throw undefined
|
|
}
|