2024-02-21 02:13:48 -08:00
|
|
|
import { Alert } from "@mantine/core";
|
|
|
|
import { IconAlertTriangle } from "@tabler/icons-react";
|
|
|
|
import { Component, ErrorInfo, ReactNode } from "react";
|
|
|
|
import { useLocation } from "react-router-dom";
|
|
|
|
|
|
|
|
interface Props {
|
|
|
|
children?: ReactNode;
|
2024-07-27 07:29:18 -07:00
|
|
|
title?: string;
|
2024-02-21 02:13:48 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
interface State {
|
|
|
|
error: Error | null;
|
|
|
|
}
|
|
|
|
|
|
|
|
class ErrorBoundary extends Component<Props, State> {
|
|
|
|
public state: State = {
|
|
|
|
error: null,
|
|
|
|
};
|
|
|
|
|
|
|
|
public static getDerivedStateFromError(error: Error): State {
|
|
|
|
// Update state so the next render will show the fallback UI.
|
|
|
|
return { error };
|
|
|
|
}
|
|
|
|
|
|
|
|
public componentDidCatch(error: Error, errorInfo: ErrorInfo) {
|
|
|
|
console.error("Uncaught error:", error, errorInfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
public render() {
|
|
|
|
if (this.state.error !== null) {
|
|
|
|
return (
|
|
|
|
<Alert
|
|
|
|
color="red"
|
2024-07-27 07:29:18 -07:00
|
|
|
title={this.props.title || "Error querying page data"}
|
2024-09-13 05:43:05 -07:00
|
|
|
icon={<IconAlertTriangle />}
|
2024-03-07 04:16:54 -08:00
|
|
|
maw={500}
|
|
|
|
mx="auto"
|
|
|
|
mt="lg"
|
2024-02-21 02:13:48 -08:00
|
|
|
>
|
|
|
|
<strong>Error:</strong> {this.state.error.message}
|
|
|
|
</Alert>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
return this.props.children;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const ResettingErrorBoundary = (props: Props) => {
|
|
|
|
const location = useLocation();
|
|
|
|
return (
|
2024-09-03 07:07:04 -07:00
|
|
|
<ErrorBoundary key={location.pathname} title={props.title}>
|
|
|
|
{props.children}
|
|
|
|
</ErrorBoundary>
|
2024-02-21 02:13:48 -08:00
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
export default ResettingErrorBoundary;
|