import {
isRouteErrorResponse,
useParams,
useRouteError,
} from '@remix-run/react'
import { type ErrorResponse } from '@remix-run/router'
import { getErrorMessage } from '#app/utils/misc.tsx'
type StatusHandler = (info: {
error: ErrorResponse
params: Record<string, string | undefined>
}) => JSX.Element | null
export function GeneralErrorBoundary({
defaultStatusHandler = ({ error }) => (
<p>
{error.status} {error.data}
</p>
),
statusHandlers,
unexpectedErrorHandler = error => <p>{getErrorMessage(error)}</p>,
}: {
defaultStatusHandler?: StatusHandler
statusHandlers?: Record<number, StatusHandler>
unexpectedErrorHandler?: (error: unknown) => JSX.Element | null
}) {
const error = useRouteError()
const params = useParams()
if (typeof document !== 'undefined') {
console.error(error)
}
return (
<div className="container mx-auto flex h-full w-full items-center justify-center bg-destructive p-20 text-h2 text-destructive-foreground">
{isRouteErrorResponse(error)
? (statusHandlers?.[error.status] ?? defaultStatusHandler)({
error,
params,
})
: unexpectedErrorHandler(error)}
</div>
)
}
Usage
export function ErrorBoundary() {
return (
<GeneralErrorBoundary
statusHandlers={{
403: ({ params }) => (
<p>You're not authorized to look at {params.sandwichId}</p>
),
}}
/>
)
}