diff --git a/src/App.tsx b/src/App.tsx index 5921c17..f017170 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -5,20 +5,23 @@ import { AuthProvider } from './contexts/AuthContext'; import { TLDrawProvider } from './contexts/TLDrawContext'; import { UserProvider } from './contexts/UserContext'; import AppRoutes from './AppRoutes'; +import { ErrorBoundary } from './components/ErrorBoundary'; import React from 'react'; const App = React.memo(() => ( - - - - - - - - - - - + + + + + + + + + + + + + )); App.displayName = import.meta.env.VITE_APP_NAME; diff --git a/src/components/ErrorBoundary.tsx b/src/components/ErrorBoundary.tsx new file mode 100644 index 0000000..b9e0d67 --- /dev/null +++ b/src/components/ErrorBoundary.tsx @@ -0,0 +1,84 @@ +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 { + 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 ( + + Something went wrong + + {this.state.error?.message || 'An unexpected error occurred'} + + { + 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 + + {import.meta.env.DEV && ( + + Error Details + + {this.state.error?.stack} + + + )} + + ); + } + + return this.props.children; + } +}
+ {this.state.error?.message || 'An unexpected error occurred'} +
+ {this.state.error?.stack} +