68 lines
1.5 KiB
TypeScript
68 lines
1.5 KiB
TypeScript
import React from "react";
|
|
|
|
type ErrorHandler = (error: Error, info: React.ErrorInfo) => void;
|
|
type ErrorHandlingComponent<Props> = (
|
|
props: Props,
|
|
error?: Error
|
|
) => React.ReactNode;
|
|
|
|
type ErrorState = { error?: Error };
|
|
|
|
function Catch<Props extends object>(
|
|
component: ErrorHandlingComponent<Props>,
|
|
errorHandler?: ErrorHandler
|
|
): React.ComponentType<Props> {
|
|
function Inner({ error, props }: { error?: Error; props: Props }) {
|
|
return <React.Fragment>{component(props, error)}</React.Fragment>;
|
|
}
|
|
|
|
return class CatchClass extends React.Component<Props, ErrorState> {
|
|
state: ErrorState = {
|
|
error: undefined,
|
|
};
|
|
|
|
static getDerivedStateFromError(error: Error) {
|
|
return { error };
|
|
}
|
|
|
|
componentDidCatch(error: Error, info: React.ErrorInfo) {
|
|
if (errorHandler) {
|
|
errorHandler(error, info);
|
|
}
|
|
}
|
|
|
|
render() {
|
|
return <Inner error={this.state.error} props={this.props} />;
|
|
}
|
|
};
|
|
}
|
|
|
|
const divStyles: React.CSSProperties = {
|
|
display: "flex",
|
|
flexDirection: "column",
|
|
alignItems: "center",
|
|
justifyContent: "center",
|
|
};
|
|
|
|
const ErrorBoundary = Catch(function (
|
|
props: React.PropsWithChildren,
|
|
error?: Error
|
|
) {
|
|
if (error) {
|
|
return (
|
|
<div style={divStyles}>
|
|
<h2>
|
|
There was an error on the page. Please reload the application and try
|
|
again.
|
|
</h2>
|
|
<p />
|
|
<p>{error.message}</p>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return <>{props.children}</>;
|
|
});
|
|
|
|
export default ErrorBoundary;
|