feat: add error boundary and loading spinner components with SWR integration

This commit is contained in:
Developer
2026-03-18 16:18:19 +08:00
parent 1f51c330dd
commit 5dd00c310f
4 changed files with 137 additions and 6 deletions
+56
View File
@@ -0,0 +1,56 @@
import React from 'react';
import { Icon } from './icons';
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) {
console.error('ErrorBoundary caught error:', error, errorInfo);
}
handleReload = () => {
window.location.reload();
};
handleGoHome = () => {
window.location.href = '/';
};
render() {
if (this.state.hasError) {
return (
<div className="error-boundary">
<div className="error-boundary__content">
<Icon name="info" size={48} />
<h2>出错了</h2>
<p>抱歉应用遇到了问题</p>
{process.env.NODE_ENV === 'development' && (
<pre className="error-boundary__details">
{this.state.error?.toString()}
</pre>
)}
<div className="error-boundary__actions">
<button onClick={this.handleGoHome} className="btn btn-secondary">
返回首页
</button>
<button onClick={this.handleReload} className="btn btn-primary">
重新加载
</button>
</div>
</div>
</div>
);
}
return this.props.children;
}
}
export default ErrorBoundary;
+10
View File
@@ -0,0 +1,10 @@
import { Icon } from './icons';
export default function LoadingSpinner({ size = 24, text = '加载中...' }) {
return (
<div className="loading-spinner">
<Icon name="spinner" size={size} className="is-spinning" />
{text && <span>{text}</span>}
</div>
);
}