mirror of
https://github.com/siteboon/claudecodeui.git
synced 2026-03-02 20:47:42 +00:00
improve: Refactor ErrorBoundary to use react-error-boundary library
This commit is contained in:
13
package-lock.json
generated
13
package-lock.json
generated
@@ -52,6 +52,7 @@
|
|||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-dropzone": "^14.2.3",
|
"react-dropzone": "^14.2.3",
|
||||||
|
"react-error-boundary": "^4.1.2",
|
||||||
"react-i18next": "^16.5.3",
|
"react-i18next": "^16.5.3",
|
||||||
"react-markdown": "^10.1.0",
|
"react-markdown": "^10.1.0",
|
||||||
"react-router-dom": "^6.8.1",
|
"react-router-dom": "^6.8.1",
|
||||||
@@ -9834,6 +9835,18 @@
|
|||||||
"react": ">= 16.8 || 18.0.0"
|
"react": ">= 16.8 || 18.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-error-boundary": {
|
||||||
|
"version": "4.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-4.1.2.tgz",
|
||||||
|
"integrity": "sha512-GQDxZ5Jd+Aq/qUxbCm1UtzmL/s++V7zKgE8yMktJiCQXCCFZnMZh9ng+6/Ne6PjNSXH0L9CjeOEREfRnq6Duag==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.12.5"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=16.13.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-i18next": {
|
"node_modules/react-i18next": {
|
||||||
"version": "16.5.3",
|
"version": "16.5.3",
|
||||||
"resolved": "https://registry.npmmirror.com/react-i18next/-/react-i18next-16.5.3.tgz",
|
"resolved": "https://registry.npmmirror.com/react-i18next/-/react-i18next-16.5.3.tgz",
|
||||||
|
|||||||
@@ -86,6 +86,7 @@
|
|||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-dropzone": "^14.2.3",
|
"react-dropzone": "^14.2.3",
|
||||||
|
"react-error-boundary": "^4.1.2",
|
||||||
"react-i18next": "^16.5.3",
|
"react-i18next": "^16.5.3",
|
||||||
"react-markdown": "^10.1.0",
|
"react-markdown": "^10.1.0",
|
||||||
"react-router-dom": "^6.8.1",
|
"react-router-dom": "^6.8.1",
|
||||||
|
|||||||
@@ -1,73 +1,77 @@
|
|||||||
import React from 'react';
|
import React, { useCallback, useState } from 'react';
|
||||||
|
import { ErrorBoundary as ReactErrorBoundary } from 'react-error-boundary';
|
||||||
|
|
||||||
class ErrorBoundary extends React.Component {
|
function ErrorFallback({ error, resetErrorBoundary, showDetails, componentStack }) {
|
||||||
constructor(props) {
|
return (
|
||||||
super(props);
|
<div className="flex flex-col items-center justify-center p-8 text-center">
|
||||||
this.state = { hasError: false, error: null, errorInfo: null };
|
<div className="bg-red-50 border border-red-200 rounded-lg p-6 max-w-md">
|
||||||
}
|
<div className="flex items-center mb-4">
|
||||||
|
<div className="flex-shrink-0">
|
||||||
static getDerivedStateFromError(error) {
|
<svg className="h-5 w-5 text-red-400" viewBox="0 0 20 20" fill="currentColor">
|
||||||
// Update state so the next render will show the fallback UI
|
<path fillRule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clipRule="evenodd" />
|
||||||
return { hasError: true };
|
</svg>
|
||||||
}
|
|
||||||
|
|
||||||
componentDidCatch(error, errorInfo) {
|
|
||||||
// Log the error details
|
|
||||||
console.error('ErrorBoundary caught an error:', error, errorInfo);
|
|
||||||
|
|
||||||
// You can also log the error to an error reporting service here
|
|
||||||
this.setState({
|
|
||||||
error: error,
|
|
||||||
errorInfo: errorInfo
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
if (this.state.hasError) {
|
|
||||||
// Fallback UI
|
|
||||||
return (
|
|
||||||
<div className="flex flex-col items-center justify-center p-8 text-center">
|
|
||||||
<div className="bg-red-50 border border-red-200 rounded-lg p-6 max-w-md">
|
|
||||||
<div className="flex items-center mb-4">
|
|
||||||
<div className="flex-shrink-0">
|
|
||||||
<svg className="h-5 w-5 text-red-400" viewBox="0 0 20 20" fill="currentColor">
|
|
||||||
<path fillRule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clipRule="evenodd" />
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<h3 className="ml-3 text-sm font-medium text-red-800">
|
|
||||||
Something went wrong
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
<div className="text-sm text-red-700">
|
|
||||||
<p className="mb-2">An error occurred while loading the chat interface.</p>
|
|
||||||
{this.props.showDetails && this.state.error && (
|
|
||||||
<details className="mt-4">
|
|
||||||
<summary className="cursor-pointer text-xs font-mono">Error Details</summary>
|
|
||||||
<pre className="mt-2 text-xs bg-red-100 p-2 rounded overflow-auto max-h-40">
|
|
||||||
{this.state.error.toString()}
|
|
||||||
{this.state.errorInfo && this.state.errorInfo.componentStack}
|
|
||||||
</pre>
|
|
||||||
</details>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div className="mt-4">
|
|
||||||
<button
|
|
||||||
onClick={() => {
|
|
||||||
this.setState({ hasError: false, error: null, errorInfo: null });
|
|
||||||
if (this.props.onRetry) this.props.onRetry();
|
|
||||||
}}
|
|
||||||
className="bg-red-600 text-white px-4 py-2 rounded text-sm hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-red-500"
|
|
||||||
>
|
|
||||||
Try Again
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<h3 className="ml-3 text-sm font-medium text-red-800">
|
||||||
|
Something went wrong
|
||||||
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
);
|
<div className="text-sm text-red-700">
|
||||||
}
|
<p className="mb-2">An error occurred while loading the chat interface.</p>
|
||||||
|
{showDetails && error && (
|
||||||
return this.props.children;
|
<details className="mt-4">
|
||||||
}
|
<summary className="cursor-pointer text-xs font-mono">Error Details</summary>
|
||||||
|
<pre className="mt-2 text-xs bg-red-100 p-2 rounded overflow-auto max-h-40">
|
||||||
|
{error.toString()}
|
||||||
|
{componentStack}
|
||||||
|
</pre>
|
||||||
|
</details>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className="mt-4">
|
||||||
|
<button
|
||||||
|
onClick={resetErrorBoundary}
|
||||||
|
className="bg-red-600 text-white px-4 py-2 rounded text-sm hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-red-500"
|
||||||
|
>
|
||||||
|
Try Again
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ErrorBoundary;
|
function ErrorBoundary({ children, showDetails = false, onRetry = undefined, resetKeys = undefined }) {
|
||||||
|
const [componentStack, setComponentStack] = useState(null);
|
||||||
|
|
||||||
|
const handleError = useCallback((error, errorInfo) => {
|
||||||
|
console.error('ErrorBoundary caught an error:', error, errorInfo);
|
||||||
|
setComponentStack(errorInfo?.componentStack || null);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleReset = useCallback(() => {
|
||||||
|
setComponentStack(null);
|
||||||
|
onRetry?.();
|
||||||
|
}, [onRetry]);
|
||||||
|
|
||||||
|
const renderFallback = useCallback(({ error, resetErrorBoundary }) => (
|
||||||
|
<ErrorFallback
|
||||||
|
error={error}
|
||||||
|
resetErrorBoundary={resetErrorBoundary}
|
||||||
|
showDetails={showDetails}
|
||||||
|
componentStack={componentStack}
|
||||||
|
/>
|
||||||
|
), [showDetails, componentStack]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ReactErrorBoundary
|
||||||
|
fallbackRender={renderFallback}
|
||||||
|
onError={handleError}
|
||||||
|
onReset={handleReset}
|
||||||
|
resetKeys={resetKeys}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</ReactErrorBoundary>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ErrorBoundary;
|
||||||
|
|||||||
Reference in New Issue
Block a user