import { Component, Suspense, type ErrorInfo, type ReactNode } from "react"; import { useLocation, useNavigate } from "@/lib/router"; import { Button } from "@/components/ui/button"; import { onChunkLoadReloadAbandoned, reloadForChunkLoadError } from "@/lib/chunk-load-recovery"; import { captureBrowserException } from "@/lib/sentry"; import { PaperclipLoading } from "./AnimatedPaperclipIcon"; type RouteErrorBoundaryInnerProps = { resetKey: string; onReset: () => void; children: ReactNode; }; type RouteErrorBoundaryState = { error: Error | null; reloading: boolean; }; class RouteErrorBoundaryInner extends Component { override state: RouteErrorBoundaryState = { error: null, reloading: false }; private stopWaitingForReload: (() => void) | null = null; static getDerivedStateFromError(error: unknown): Partial { return { error: error instanceof Error ? error : new Error(String(error)) }; } override componentDidCatch(error: unknown, info: ErrorInfo): void { this.stopWaiting(); if (reloadForChunkLoadError(error)) { this.setState({ reloading: true }); this.stopWaitingForReload = onChunkLoadReloadAbandoned(() => { this.stopWaitingForReload = null; this.setState({ reloading: false }); this.report(error, info); }); return; } this.report(error, info); } override componentWillUnmount(): void { this.stopWaiting(); } private stopWaiting(): void { this.stopWaitingForReload?.(); this.stopWaitingForReload = null; } private report(error: unknown, info: ErrorInfo): void { console.error("Page render failed", { error, componentStack: info.componentStack }); captureBrowserException(error, { boundary: "route", componentStack: info.componentStack }); } override componentDidUpdate(prevProps: RouteErrorBoundaryInnerProps): void { // A render throw with no boundary unmounts the whole app, so navigating // away (back button included) can't recover without a hard refresh. We sit // above the routed , so reset whenever the route changes. if (this.state.error && prevProps.resetKey !== this.props.resetKey) { this.stopWaiting(); this.setState({ error: null, reloading: false }); } } override render() { const { error, reloading } = this.state; if (!error) return this.props.children; if (reloading) return ; return (

This page hit an error

Something went wrong while rendering this page. You can go back and try again, or reload.

          {error.message}
        
); } } export function RouteErrorBoundary({ children }: { children: ReactNode }) { const location = useLocation(); const navigate = useNavigate(); const resetKey = `${location.pathname}${location.search}`; return ( navigate(-1)}> }>{children} ); }