From: root Date: Thu, 27 Aug 2026 10:14:47 +0000 (+0800) Subject: split: 修复无痕模式白屏(localStorage 防御 + 全局错误边界) X-Git-Url: http://acesimba.cloud/gitweb/?a=commitdiff_plain;h=f8ee907e6574b17a5e5817ee604603dc9b17631a;p=words.git split: 修复无痕模式白屏(localStorage 防御 + 全局错误边界) - auth.js: localStorage 读写包 try-catch, 无痕/隐私模式禁止访问时不再崩溃 - ErrorBoundary.js: 新增全局错误边界, 渲染期异常显示错误文字而非白屏 - index.js: 用 ErrorBoundary 包裹 Co-Authored-By: CodeBuddy Code --- 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( - + + + );