73 lines
1.9 KiB
TypeScript
73 lines
1.9 KiB
TypeScript
// Copyright 2025 Signal Messenger, LLC
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
import type { ReactNode, ErrorInfo } from 'react';
|
|
import React, { Component, useCallback } from 'react';
|
|
import { createLogger } from '../logging/log.js';
|
|
import * as Errors from '../types/errors.js';
|
|
|
|
const log = createLogger('DonationsErrorBoundary');
|
|
|
|
type ErrorBoundaryProps = Readonly<{
|
|
children: ReactNode;
|
|
onError: (error: unknown, info: ErrorInfo) => void;
|
|
fallback: (error: unknown) => ReactNode;
|
|
}>;
|
|
|
|
type ErrorBoundaryState = {
|
|
caught?: { error: unknown };
|
|
};
|
|
|
|
class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
|
|
// eslint-disable-next-line react/state-in-constructor
|
|
override state: ErrorBoundaryState = {};
|
|
|
|
static getDerivedStateFromError(error: unknown) {
|
|
return { caught: { error } };
|
|
}
|
|
|
|
override componentDidCatch(error: unknown, info: ErrorInfo) {
|
|
this.props.onError(error, info);
|
|
}
|
|
|
|
override render() {
|
|
if (this.state.caught != null) {
|
|
return this.props.fallback(this.state.caught.error);
|
|
}
|
|
|
|
return this.props.children;
|
|
}
|
|
}
|
|
|
|
export type DonationsErrorBoundaryProps = Readonly<{
|
|
children: ReactNode;
|
|
}>;
|
|
|
|
export function DonationsErrorBoundary(
|
|
props: DonationsErrorBoundaryProps
|
|
): JSX.Element {
|
|
const fallback = useCallback(() => {
|
|
return <div className="DonationsErrorBoundary" />;
|
|
}, []);
|
|
|
|
const handleError = useCallback((error: unknown, info: ErrorInfo) => {
|
|
log.error(
|
|
'DonationsErrorBoundary: Caught error',
|
|
Errors.toLogFormat(error),
|
|
info.componentStack
|
|
);
|
|
|
|
if (window.reduxActions) {
|
|
window.reduxActions.globalModals.showDebugLogErrorModal({
|
|
description: window.i18n(
|
|
'icu:DonationsErrorBoundary__DonationUnexpectedError'
|
|
),
|
|
});
|
|
}
|
|
}, []);
|
|
|
|
return (
|
|
<ErrorBoundary fallback={fallback} onError={handleError}>
|
|
{props.children}
|
|
</ErrorBoundary>
|
|
);
|
|
}
|