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.
22 lines
411 B
JavaScript
22 lines
411 B
JavaScript
'use client'
|
|
|
|
import { useState } from 'react'
|
|
|
|
export default function Page() {
|
|
const [clicked, setClicked] = useState(false)
|
|
if (clicked) {
|
|
// eslint-disable-next-line no-throw-literal -- testing bad values on purpose
|
|
throw undefined
|
|
}
|
|
return (
|
|
<button
|
|
id="error-trigger-button"
|
|
onClick={() => {
|
|
setClicked(true)
|
|
}}
|
|
>
|
|
Trigger Error!
|
|
</button>
|
|
)
|
|
}
|