From ac62da2ad8c7af3d29bb739ff6fbdd16aae04a80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E8=88=AA=E5=AE=87?= <3364451258@qq.com> Date: Sun, 31 May 2026 13:40:05 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=20React=20Error=20Bo?= =?UTF-8?q?undary=20=E7=BB=84=E4=BB=B6=E9=98=B2=E6=AD=A2=E6=B8=B2=E6=9F=93?= =?UTF-8?q?=E5=BC=82=E5=B8=B8=E7=99=BD=E5=B1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.tsx | 23 +++++---- src/components/common/ErrorBoundary.tsx | 62 +++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 8 deletions(-) create mode 100644 src/components/common/ErrorBoundary.tsx diff --git a/src/App.tsx b/src/App.tsx index 27d7d32..c45d60e 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -2,6 +2,7 @@ import { useState } from 'react'; import MainMenu from './components/menu/MainMenu'; import GameView from './components/game/GameView'; import ReplayView from './components/replay/ReplayView'; +import ErrorBoundary from './components/common/ErrorBoundary'; import './App.css'; type Page = 'menu' | 'game' | 'replay'; @@ -13,15 +14,21 @@ function App() { const handleReplayStart = () => setPage('replay'); const handleBackToMenu = () => setPage('menu'); - if (page === 'game') return ; - if (page === 'replay') return ; + let content: React.ReactNode; + if (page === 'game') { + content = ; + } else if (page === 'replay') { + content = ; + } else { + content = ( + + ); + } - return ( - - ); + return {content}; } export default App; diff --git a/src/components/common/ErrorBoundary.tsx b/src/components/common/ErrorBoundary.tsx new file mode 100644 index 0000000..c9410cb --- /dev/null +++ b/src/components/common/ErrorBoundary.tsx @@ -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 { + 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 ( + + 程序出错了 + + {this.state.error?.message} + + { + 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', + }} + > + 重新加载 + + + ); + } + return this.props.children; + } +}
+ {this.state.error?.message} +