80 lines
1.9 KiB
JavaScript
80 lines
1.9 KiB
JavaScript
import React from 'react';
|
|
import { logError } from '../utils/errorLogger';
|
|
|
|
class ErrorBoundary extends React.Component {
|
|
constructor(props) {
|
|
super(props);
|
|
this.state = { hasError: false, error: null };
|
|
}
|
|
|
|
static getDerivedStateFromError(error) {
|
|
return { hasError: true, error };
|
|
}
|
|
|
|
componentDidCatch(error, errorInfo) {
|
|
// Extract component stack for richer context
|
|
const componentInfo = {
|
|
component: errorInfo?.componentStack || null,
|
|
props: this.props,
|
|
};
|
|
|
|
logError(error, componentInfo);
|
|
}
|
|
|
|
handleRetry = () => {
|
|
this.setState({ hasError: false, error: null });
|
|
};
|
|
|
|
renderDefaultFallback() {
|
|
return (
|
|
<div
|
|
style={{
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
padding: '2rem',
|
|
textAlign: 'center',
|
|
minHeight: '200px',
|
|
}}
|
|
>
|
|
<h2 style={{ marginBottom: '0.5rem', color: '#e53e3e' }}>
|
|
Something went wrong
|
|
</h2>
|
|
<p style={{ marginBottom: '1rem', color: '#718096', fontSize: '0.9rem' }}>
|
|
An unexpected error occurred. You can try again.
|
|
</p>
|
|
<button
|
|
onClick={this.handleRetry}
|
|
style={{
|
|
padding: '0.5rem 1.25rem',
|
|
fontSize: '0.9rem',
|
|
fontWeight: 600,
|
|
color: '#fff',
|
|
backgroundColor: '#3182ce',
|
|
border: 'none',
|
|
borderRadius: '6px',
|
|
cursor: 'pointer',
|
|
}}
|
|
>
|
|
Try Again
|
|
</button>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
render() {
|
|
if (this.state.hasError) {
|
|
// Allow custom fallback render function
|
|
if (typeof this.props.fallback === 'function') {
|
|
return this.props.fallback(this.state.error, this.handleRetry);
|
|
}
|
|
|
|
return this.renderDefaultFallback();
|
|
}
|
|
|
|
return this.props.children;
|
|
}
|
|
}
|
|
|
|
export default ErrorBoundary; |