From f8ee907e6574b17a5e5817ee604603dc9b17631a Mon Sep 17 00:00:00 2001 From: root Date: Thu, 27 Aug 2026 18:14:47 +0800 Subject: [PATCH] =?utf8?q?split:=20=E4=BF=AE=E5=A4=8D=E6=97=A0=E7=97=95?= =?utf8?q?=E6=A8=A1=E5=BC=8F=E7=99=BD=E5=B1=8F(localStorage=20=E9=98=B2?= =?utf8?q?=E5=BE=A1=20+=20=E5=85=A8=E5=B1=80=E9=94=99=E8=AF=AF=E8=BE=B9?= =?utf8?q?=E7=95=8C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit - auth.js: localStorage 读写包 try-catch, 无痕/隐私模式禁止访问时不再崩溃 - ErrorBoundary.js: 新增全局错误边界, 渲染期异常显示错误文字而非白屏 - index.js: 用 ErrorBoundary 包裹 Co-Authored-By: CodeBuddy Code --- frontend/src/ErrorBoundary.js | 35 +++++++++++++++++++++++++++++++++++ frontend/src/auth.js | 18 +++++++++++++++--- frontend/src/index.js | 5 ++++- 3 files changed, 54 insertions(+), 4 deletions(-) create mode 100644 frontend/src/ErrorBoundary.js diff --git a/frontend/src/ErrorBoundary.js b/frontend/src/ErrorBoundary.js new file mode 100644 index 0000000..cd0702e --- /dev/null +++ b/frontend/src/ErrorBoundary.js @@ -0,0 +1,35 @@ +import React from 'react'; + +// 全局错误边界:捕获渲染期异常并显示, 避免生产构建下整页白屏无提示 +export default class ErrorBoundary extends React.Component { + constructor(props) { + super(props); + this.state = { hasError: false, error: null, info: null }; + } + + static getDerivedStateFromError(error) { + return { hasError: true, error }; + } + + componentDidCatch(error, info) { + this.setState({ info }); + console.error('App crashed:', error, info); + } + + render() { + if (this.state.hasError) { + return ( +
+

页面加载出错

+
+            {this.state.error && (this.state.error.stack || this.state.error.toString())}
+          
+ +
+ ); + } + return this.props.children; + } +} diff --git a/frontend/src/auth.js b/frontend/src/auth.js index 4a4bcf0..7051b55 100644 --- a/frontend/src/auth.js +++ b/frontend/src/auth.js @@ -4,16 +4,28 @@ import { API_BASE } from './api'; const TOKEN_KEY = 'words_auth_token'; +// 无痕/隐私模式下部分浏览器会禁止 localStorage 访问并抛 SecurityError, +// 这里统一兜底, 避免初始化时崩溃导致整页白屏。 +function safeGet(key) { + try { return localStorage.getItem(key); } catch (e) { return null; } +} +function safeSet(key, val) { + try { localStorage.setItem(key, val); } catch (e) {} +} +function safeRemove(key) { + try { localStorage.removeItem(key); } catch (e) {} +} + export function getToken() { - return localStorage.getItem(TOKEN_KEY) || ''; + return safeGet(TOKEN_KEY) || ''; } export function setToken(t) { - localStorage.setItem(TOKEN_KEY, t); + safeSet(TOKEN_KEY, t); } export function clearToken() { - localStorage.removeItem(TOKEN_KEY); + safeRemove(TOKEN_KEY); } export function isLoggedIn() { diff --git a/frontend/src/index.js b/frontend/src/index.js index f24def9..3a56c9e 100644 --- a/frontend/src/index.js +++ b/frontend/src/index.js @@ -2,13 +2,16 @@ import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css'; import App from './App'; +import ErrorBoundary from './ErrorBoundary'; import { isLoggedIn } from './auth'; import reportWebVitals from './reportWebVitals'; const root = ReactDOM.createRoot(document.getElementById('root')); root.render( - + + + ); -- 2.43.0