ErrorBoundary.tsx•2.06 kB
import React, { Component, ErrorInfo, ReactNode } from 'react';
interface Props {
children: ReactNode;
fallback?: ReactNode;
onError?: (error: Error, errorInfo: ErrorInfo) => void;
}
interface State {
hasError: boolean;
error?: Error;
errorInfo?: ErrorInfo;
}
export class ErrorBoundary extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error: Error): State {
return { hasError: true, error };
}
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
this.setState({ errorInfo });
// 调用错误回调
if (this.props.onError) {
this.props.onError(error, errorInfo);
}
// 记录错误
console.error('ErrorBoundary捕获到错误:', error, errorInfo);
}
handleRetry = () => {
this.setState({ hasError: false, error: undefined, errorInfo: undefined });
};
render() {
if (this.state.hasError) {
if (this.props.fallback) {
return this.props.fallback;
}
return (
<div className="error-boundary">
<div className="error-content">
<h2>出现了一些问题</h2>
<p>应用程序遇到了意外错误,请尝试刷新页面或联系技术支持。</p>
<div className="error-actions">
<button onClick={this.handleRetry} className="retry-btn">
重试
</button>
<button onClick={() => window.location.reload()} className="refresh-btn">
刷新页面
</button>
</div>
{process.env.NODE_ENV === 'development' && this.state.error && (
<details className="error-details">
<summary>错误详情 (开发模式)</summary>
<pre>{this.state.error.toString()}</pre>
<pre>{this.state.errorInfo?.componentStack}</pre>
</details>
)}
</div>
</div>
);
}
return this.props.children;
}
}