/ easyshell-web / src / components / ErrorBoundary.tsx
ErrorBoundary.tsx
 1  import React from 'react';
 2  import { Result, Button } from 'antd';
 3  import { withTranslation, type WithTranslation } from 'react-i18next';
 4  
 5  interface ErrorBoundaryProps extends WithTranslation {
 6    children: React.ReactNode;
 7  }
 8  
 9  interface ErrorBoundaryState {
10    hasError: boolean;
11    error: Error | null;
12  }
13  
14  /**
15   * Error boundary wrapper for catching render errors.
16   * Displays a friendly error message with a retry button.
17   */
18  class ErrorBoundaryInner extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {
19    constructor(props: ErrorBoundaryProps) {
20      super(props);
21      this.state = { hasError: false, error: null };
22    }
23  
24    static getDerivedStateFromError(error: Error): ErrorBoundaryState {
25      return { hasError: true, error };
26    }
27  
28    componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void {
29      console.error('ErrorBoundary caught an error:', error, errorInfo);
30    }
31  
32    handleReset = (): void => {
33      this.setState({ hasError: false, error: null });
34    };
35  
36    render(): React.ReactNode {
37      const { t } = this.props;
38      if (this.state.hasError) {
39        return (
40          <Result
41            status="error"
42            title={t('error.pageError')}
43            subTitle={this.state.error?.message || t('error.unknownError')}
44            extra={[
45              <Button key="retry" type="primary" onClick={this.handleReset}>
46                {t('common.retry')}
47              </Button>,
48              <Button key="home" onClick={() => (window.location.href = '/')}>
49                {t('error.backHome')}
50              </Button>,
51            ]}
52          />
53        );
54      }
55  
56      return this.props.children;
57    }
58  }
59  
60  const ErrorBoundary = withTranslation()(ErrorBoundaryInner);
61  export default ErrorBoundary;