diff --git a/packages/react-router/src/CatchBoundary.tsx b/packages/react-router/src/CatchBoundary.tsx
index f55a250ab1..87203a2279 100644
--- a/packages/react-router/src/CatchBoundary.tsx
+++ b/packages/react-router/src/CatchBoundary.tsx
@@ -11,32 +11,36 @@ export class CatchBoundary extends React.Component<{
errorComponent?: ErrorRouteComponent
onCatch?: (error: Error, errorInfo: ErrorInfo) => void
}> {
- state = { error: null } as { error: Error | null; resetKey?: unknown }
+ state = { error: null, hasError: false } as {
+ error: Error | null
+ hasError: boolean
+ resetKey?: unknown
+ }
static getDerivedStateFromProps(
props: { getResetKey: () => unknown },
- state: { resetKey?: unknown; error: Error | null },
+ state: { resetKey?: unknown; error: Error | null; hasError: boolean },
) {
const resetKey = props.getResetKey()
- if (state.error && state.resetKey !== resetKey) {
- return { resetKey, error: null }
+ if (state.hasError && state.resetKey !== resetKey) {
+ return { resetKey, error: null, hasError: false }
}
return { resetKey }
}
static getDerivedStateFromError(error: Error) {
- return { error }
+ return { error, hasError: true }
}
reset = () => {
- this.setState({ error: null })
+ this.setState({ error: null, hasError: false })
}
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
this.props.onCatch?.(error, errorInfo)
}
render() {
- const error = this.state.error
- if (error) {
+ if (this.state.hasError) {
+ const error = this.state.error
const element = React.createElement(
this.props.errorComponent ?? ErrorComponent,
{
@@ -88,7 +92,7 @@ export function ErrorComponent({ error }: { error: any }) {
overflow: 'auto',
}}
>
- {error.message ? {error.message} : null}
+ {error?.message ? {error.message} : null}
) : null}
diff --git a/packages/react-router/tests/errorComponent.test.tsx b/packages/react-router/tests/errorComponent.test.tsx
index b5ee4b6709..d6e577acf9 100644
--- a/packages/react-router/tests/errorComponent.test.tsx
+++ b/packages/react-router/tests/errorComponent.test.tsx
@@ -868,3 +868,36 @@ describe('notFoundComponent is rendered when an error is thrown in params.parse'
expect(notFoundComponent).toBeInTheDocument()
})
})
+
+test.each([
+ { desc: 'undefined', value: undefined, expected: 'undefined' },
+ { desc: 'null', value: null, expected: 'null' },
+ { desc: 'empty string', value: '', expected: '""' },
+])(
+ 'errorComponent is rendered when component throws falsy value: $desc',
+ async ({ value, expected }) => {
+ const rootRoute = createRootRoute()
+ const indexRoute = createRoute({
+ getParentRoute: () => rootRoute,
+ path: '/',
+ component: function Home() {
+ throw value
+ },
+ errorComponent: ({ error }) => (
+