Spaces:
Running
on
A100
Running
on
A100
| import React, { Component, ReactNode } from 'react'; | |
| interface Props { | |
| children: ReactNode; | |
| componentName?: string; | |
| } | |
| interface State { | |
| hasError: boolean; | |
| error: Error | null; | |
| errorInfo: React.ErrorInfo | null; | |
| } | |
| class ErrorBoundary extends Component<Props, State> { | |
| constructor(props: Props) { | |
| super(props); | |
| this.state = { hasError: false, error: null, errorInfo: null }; | |
| } | |
| static getDerivedStateFromError(error: Error): State { | |
| return { hasError: true, error, errorInfo: null }; | |
| } | |
| componentDidCatch(error: Error, errorInfo: React.ErrorInfo) { | |
| console.error('ErrorBoundary caught an error:', error, errorInfo); | |
| this.setState({ | |
| error, | |
| errorInfo | |
| }); | |
| } | |
| handleRetry = () => { | |
| this.setState({ hasError: false, error: null, errorInfo: null }); | |
| }; | |
| handleCopyError = () => { | |
| const { error, errorInfo } = this.state; | |
| const { componentName } = this.props; | |
| const errorText = ` | |
| Component: ${componentName || 'Unknown'} | |
| Error: ${error?.message || 'Unknown error'} | |
| Stack: ${error?.stack || 'No stack trace available'} | |
| Component Stack: ${errorInfo?.componentStack || 'No component stack available'} | |
| Timestamp: ${new Date().toISOString()} | |
| `.trim(); | |
| navigator.clipboard.writeText(errorText).then(() => { | |
| alert('Error details copied to clipboard!'); | |
| }).catch(() => { | |
| // Fallback for older browsers | |
| const textArea = document.createElement('textarea'); | |
| textArea.value = errorText; | |
| document.body.appendChild(textArea); | |
| textArea.select(); | |
| document.execCommand('copy'); | |
| document.body.removeChild(textArea); | |
| alert('Error details copied to clipboard!'); | |
| }); | |
| }; | |
| render() { | |
| if (this.state.hasError) { | |
| const { componentName } = this.props; | |
| const { error, errorInfo } = this.state; | |
| return ( | |
| <div className="flex flex-col items-center justify-center p-8 bg-red-50 border border-red-200 rounded-lg m-4"> | |
| <div className="text-center mb-6"> | |
| <h2 className="text-xl font-semibold text-red-800 mb-2"> | |
| Sorry, something went wrong | |
| </h2> | |
| <p className="text-red-600 mb-4"> | |
| {componentName ? `An error occurred in the ${componentName} component.` : 'An unexpected error occurred.'} | |
| </p> | |
| <button | |
| onClick={this.handleRetry} | |
| className="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 transition-colors mr-2" | |
| > | |
| Try Again | |
| </button> | |
| <button | |
| onClick={this.handleCopyError} | |
| className="px-4 py-2 bg-gray-600 text-white rounded hover:bg-gray-700 transition-colors" | |
| > | |
| Copy Error Details | |
| </button> | |
| </div> | |
| <details className="w-full max-w-4xl"> | |
| <summary className="cursor-pointer text-red-700 font-medium mb-2 hover:text-red-800"> | |
| Show Error Details (for developers) | |
| </summary> | |
| <div className="bg-gray-100 p-4 rounded border text-sm font-mono overflow-auto max-h-96"> | |
| <div className="mb-4"> | |
| <strong className="text-red-700">Error Message:</strong> | |
| <pre className="mt-1 whitespace-pre-wrap text-red-800"> | |
| {error?.message || 'Unknown error'} | |
| </pre> | |
| </div> | |
| <div className="mb-4"> | |
| <strong className="text-red-700">Stack Trace:</strong> | |
| <pre className="mt-1 whitespace-pre-wrap text-gray-800 text-xs"> | |
| {error?.stack || 'No stack trace available'} | |
| </pre> | |
| </div> | |
| {errorInfo?.componentStack && ( | |
| <div className="mb-4"> | |
| <strong className="text-red-700">Component Stack:</strong> | |
| <pre className="mt-1 whitespace-pre-wrap text-gray-800 text-xs"> | |
| {errorInfo.componentStack} | |
| </pre> | |
| </div> | |
| )} | |
| <div className="text-xs text-gray-600"> | |
| <strong>Timestamp:</strong> {new Date().toISOString()} | |
| </div> | |
| </div> | |
| </details> | |
| </div> | |
| ); | |
| } | |
| return this.props.children; | |
| } | |
| } | |
| export default ErrorBoundary; | |