85 lines
2.3 KiB
TypeScript
85 lines
2.3 KiB
TypeScript
import React, { Component, ErrorInfo, ReactNode } from 'react';
|
|
|
|
interface Props {
|
|
children: ReactNode;
|
|
fallback?: ReactNode;
|
|
}
|
|
|
|
interface State {
|
|
hasError: boolean;
|
|
error: Error | null;
|
|
}
|
|
|
|
export class ErrorBoundary extends Component<Props, State> {
|
|
public state: State = {
|
|
hasError: false,
|
|
error: null,
|
|
};
|
|
|
|
public static getDerivedStateFromError(error: Error): State {
|
|
return { hasError: true, error };
|
|
}
|
|
|
|
public componentDidCatch(error: Error, errorInfo: ErrorInfo) {
|
|
console.error('Uncaught error:', error, errorInfo);
|
|
}
|
|
|
|
public render() {
|
|
if (this.state.hasError) {
|
|
if (this.props.fallback) {
|
|
return this.props.fallback;
|
|
}
|
|
return (
|
|
<div style={{
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
minHeight: '100vh',
|
|
fontFamily: 'system-ui, -apple-system, sans-serif',
|
|
padding: '2rem',
|
|
textAlign: 'center',
|
|
}}>
|
|
<h1 style={{ color: '#dc2626', marginBottom: '1rem' }}>Something went wrong</h1>
|
|
<p style={{ color: '#6b7280', marginBottom: '1.5rem' }}>
|
|
{this.state.error?.message || 'An unexpected error occurred'}
|
|
</p>
|
|
<button
|
|
onClick={() => {
|
|
this.setState({ hasError: false, error: null });
|
|
window.location.reload();
|
|
}}
|
|
style={{
|
|
padding: '0.75rem 1.5rem',
|
|
backgroundColor: '#3b82f6',
|
|
color: 'white',
|
|
border: 'none',
|
|
borderRadius: '0.5rem',
|
|
cursor: 'pointer',
|
|
fontSize: '1rem',
|
|
}}
|
|
>
|
|
Reload Application
|
|
</button>
|
|
{import.meta.env.DEV && (
|
|
<details style={{ marginTop: '2rem', textAlign: 'left', maxWidth: '600px' }}>
|
|
<summary style={{ cursor: 'pointer', color: '#6b7280' }}>Error Details</summary>
|
|
<pre style={{
|
|
backgroundColor: '#f3f4f6',
|
|
padding: '1rem',
|
|
borderRadius: '0.5rem',
|
|
overflow: 'auto',
|
|
fontSize: '0.875rem',
|
|
}}>
|
|
{this.state.error?.stack}
|
|
</pre>
|
|
</details>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return this.props.children;
|
|
}
|
|
}
|