mirror of
https://github.com/LHY0125/Gobang-Game.git
synced 2026-06-29 00:45:55 +08:00
feat: 添加 React Error Boundary 组件防止渲染异常白屏
This commit is contained in:
+15
-8
@@ -2,6 +2,7 @@ import { useState } from 'react';
|
|||||||
import MainMenu from './components/menu/MainMenu';
|
import MainMenu from './components/menu/MainMenu';
|
||||||
import GameView from './components/game/GameView';
|
import GameView from './components/game/GameView';
|
||||||
import ReplayView from './components/replay/ReplayView';
|
import ReplayView from './components/replay/ReplayView';
|
||||||
|
import ErrorBoundary from './components/common/ErrorBoundary';
|
||||||
import './App.css';
|
import './App.css';
|
||||||
|
|
||||||
type Page = 'menu' | 'game' | 'replay';
|
type Page = 'menu' | 'game' | 'replay';
|
||||||
@@ -13,15 +14,21 @@ function App() {
|
|||||||
const handleReplayStart = () => setPage('replay');
|
const handleReplayStart = () => setPage('replay');
|
||||||
const handleBackToMenu = () => setPage('menu');
|
const handleBackToMenu = () => setPage('menu');
|
||||||
|
|
||||||
if (page === 'game') return <GameView onBackToMenu={handleBackToMenu} />;
|
let content: React.ReactNode;
|
||||||
if (page === 'replay') return <ReplayView onBackToMenu={handleBackToMenu} />;
|
if (page === 'game') {
|
||||||
|
content = <GameView onBackToMenu={handleBackToMenu} />;
|
||||||
|
} else if (page === 'replay') {
|
||||||
|
content = <ReplayView onBackToMenu={handleBackToMenu} />;
|
||||||
|
} else {
|
||||||
|
content = (
|
||||||
|
<MainMenu
|
||||||
|
onGameStart={handleGameStart}
|
||||||
|
onReplayStart={handleReplayStart}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return <ErrorBoundary>{content}</ErrorBoundary>;
|
||||||
<MainMenu
|
|
||||||
onGameStart={handleGameStart}
|
|
||||||
onReplayStart={handleReplayStart}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default App;
|
export default App;
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
import { Component, type ReactNode } from 'react';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
children: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface State {
|
||||||
|
hasError: boolean;
|
||||||
|
error: Error | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class ErrorBoundary extends Component<Props, State> {
|
||||||
|
constructor(props: Props) {
|
||||||
|
super(props);
|
||||||
|
this.state = { hasError: false, error: null };
|
||||||
|
}
|
||||||
|
|
||||||
|
static getDerivedStateFromError(error: Error): State {
|
||||||
|
return { hasError: true, error };
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
if (this.state.hasError) {
|
||||||
|
return (
|
||||||
|
<div style={{
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
height: '100vh',
|
||||||
|
color: '#F5DEB3',
|
||||||
|
background: '#3C2415',
|
||||||
|
gap: 16,
|
||||||
|
fontFamily: 'Microsoft YaHei, sans-serif',
|
||||||
|
}}>
|
||||||
|
<h2>程序出错了</h2>
|
||||||
|
<pre style={{ fontSize: 14, opacity: 0.7 }}>
|
||||||
|
{this.state.error?.message}
|
||||||
|
</pre>
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
this.setState({ hasError: false, error: null });
|
||||||
|
window.location.reload();
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
padding: '10px 24px',
|
||||||
|
fontSize: 16,
|
||||||
|
border: '2px solid #8B7355',
|
||||||
|
borderRadius: 6,
|
||||||
|
background: '#DEB887',
|
||||||
|
color: '#3C2415',
|
||||||
|
cursor: 'pointer',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
重新加载
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return this.props.children;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user