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;