* wip * wip * wip * format * wip(mobile): lint and format * cleanup * nits * nits * idiomatic react * nit * format all root files
52 lines
1.5 KiB
TypeScript
52 lines
1.5 KiB
TypeScript
import type { PropsWithChildren } from 'react';
|
|
import { ErrorBoundary } from 'react-error-boundary';
|
|
import { useLocation } from 'react-router-dom';
|
|
import { useQueryErrorResetBoundary } from '@tanstack/react-query';
|
|
import { reportError } from '@/lib/errors';
|
|
import {
|
|
RouteErrorFallback,
|
|
TopLevelErrorFallback,
|
|
} from '@/components/error-fallback';
|
|
|
|
/** Catches render crashes OUTSIDE the router so bootstrap failures still recover. */
|
|
export function TopLevelErrorBoundary({ children }: PropsWithChildren) {
|
|
return (
|
|
<ErrorBoundary
|
|
FallbackComponent={TopLevelErrorFallback}
|
|
onError={(error, info) =>
|
|
reportError(error, {
|
|
boundary: 'top',
|
|
componentStack: info.componentStack,
|
|
})
|
|
}
|
|
>
|
|
{children}
|
|
</ErrorBoundary>
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Route-scoped boundary. Resets on pathname change and clears the React
|
|
* Query error cache on retry so stale failures don't stick.
|
|
*/
|
|
export function RouteErrorBoundary({ children }: PropsWithChildren) {
|
|
const location = useLocation();
|
|
const { reset: resetQueries } = useQueryErrorResetBoundary();
|
|
return (
|
|
<ErrorBoundary
|
|
FallbackComponent={RouteErrorFallback}
|
|
onError={(error, info) =>
|
|
reportError(error, {
|
|
boundary: 'route',
|
|
pathname: location.pathname,
|
|
componentStack: info.componentStack,
|
|
})
|
|
}
|
|
onReset={() => resetQueries()}
|
|
resetKeys={[location.pathname]}
|
|
>
|
|
{children}
|
|
</ErrorBoundary>
|
|
);
|
|
}
|