mirror of
https://github.com/hanzoai/next.js.git
synced 2026-10-30 14:46:38 +00:00
This PR adds `unstable_catchError()` API for a granular custom error boundary. The error component generated by this API is not a true component format, as the wrapper provides additional args. Therefore, the API is a function call by design rather than a boundary component to avoid merging the `errorInfo` with the user-provided props from the wrapper. This API works for both the App/Pages Router. However, `retry()` is not allowed in Pages Router as it depends on `router.refresh()`, and will throw. Also, it's exported from `next/error` as there was already an `Error` component for the [Pages Router](https://nextjs.org/docs/pages/building-your-application/routing/custom-error#reusing-the-built-in-error-page). ### DevTools <img width="508" height="90" alt="CleanShot 2026-03-13 at 03 02 46@2x" src="https://github.com/user-attachments/assets/8b79b1f6-877d-4901-99f7-6a2b4d3e34fe" /> Docs to follow up: https://github.com/vercel/next.js/pull/89847 Closes NAR-768 --------- Co-authored-by: Josh Story <[email protected]>
61 lines
1.4 KiB
TypeScript
61 lines
1.4 KiB
TypeScript
import { useState } from 'react'
|
|
import { unstable_catchError, type ErrorInfo } from 'next/error'
|
|
|
|
function ErrorFallback(
|
|
{ clearError }: { clearError: () => void },
|
|
{ error, reset, unstable_retry }: ErrorInfo
|
|
) {
|
|
const [retryError, setRetryError] = useState<string | null>(null)
|
|
|
|
return (
|
|
<>
|
|
<p id="pages-error-message">{error.message}</p>
|
|
<button
|
|
id="pages-reset"
|
|
onClick={() => {
|
|
clearError()
|
|
reset()
|
|
}}
|
|
>
|
|
Reset
|
|
</button>
|
|
<button
|
|
id="pages-retry"
|
|
onClick={() => {
|
|
try {
|
|
unstable_retry()
|
|
} catch (error) {
|
|
setRetryError((error as Error).message)
|
|
}
|
|
}}
|
|
>
|
|
Retry
|
|
</button>
|
|
{retryError ? <p id="pages-retry-error">{retryError}</p> : null}
|
|
</>
|
|
)
|
|
}
|
|
|
|
const ErrorBoundary = unstable_catchError(ErrorFallback)
|
|
|
|
function ErrorThrower({ shouldThrow }: { shouldThrow: boolean }) {
|
|
if (shouldThrow) {
|
|
throw new Error('this is a pages test')
|
|
}
|
|
|
|
return null
|
|
}
|
|
|
|
export default function Page() {
|
|
const [shouldThrow, setShouldThrow] = useState(false)
|
|
|
|
return (
|
|
<ErrorBoundary clearError={() => setShouldThrow(false)}>
|
|
<button id="pages-trigger" onClick={() => setShouldThrow(true)}>
|
|
Trigger Error!
|
|
</button>
|
|
<ErrorThrower shouldThrow={shouldThrow} />
|
|
</ErrorBoundary>
|
|
)
|
|
}
|