Files
vf_react/docs/ERROR_FIX_REPORT.md
zdl 09db05c448 docs: 将所有文档迁移到 docs/ 目录
- 移动42个文档文件到 docs/ 目录
  - 更新 .gitignore 允许 docs/ 下的 .md 文件
  - 删除根目录下的重复文档文件

  📁 文档分类:
  - StockDetailPanel 重构文档(3个)
  - PostHog 集成文档(6个)
  - 系统架构和API文档(33个)

  🤖 Generated with [Claude Code](https://claude.com/claude-code)

  Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-30 14:51:22 +08:00

9.9 KiB
Raw Permalink Blame History

黑屏问题修复报告

🔍 问题描述

现象: 注册页面点击"获取二维码"按钮API 请求失败时页面变成黑屏

根本原因:

  1. 缺少全局 ErrorBoundary - 组件错误未被捕获,导致整个 React 应用崩溃
  2. 缺少 Promise rejection 处理 - 异步错误AxiosError未被捕获
  3. ErrorBoundary 组件未正确导出 - 虽然组件存在但无法使用
  4. 错误提示被注释 - 用户无法看到具体错误信息

已实施的修复方案

1. 修复 ErrorBoundary 导出 ✓

文件: src/components/ErrorBoundary.js

问题: 文件末尾只有 export 没有完整导出语句

修复:

// ❌ 修复前
export

// ✅ 修复后
export default ErrorBoundary;

2. 在 App.js 添加全局 ErrorBoundary ✓

文件: src/App.js

修复: 在最外层添加 ErrorBoundary 包裹

export default function App() {
    return (
        <ChakraProvider theme={theme}>
            <ErrorBoundary>  {/* ✅ 添加全局错误边界 */}
                <AuthProvider>
                    <AppContent />
                </AuthProvider>
            </ErrorBoundary>
        </ChakraProvider>
    );
}

效果: 捕获所有 React 组件渲染错误,防止整个应用崩溃


3. 添加全局 Promise Rejection 处理 ✓

文件: src/App.js

问题: ErrorBoundary 只能捕获同步错误,无法捕获异步 Promise rejection

修复: 添加全局事件监听器

export default function App() {
    // 全局错误处理:捕获未处理的 Promise rejection
    useEffect(() => {
        const handleUnhandledRejection = (event) => {
            console.error('未捕获的 Promise rejection:', event.reason);
            event.preventDefault(); // 阻止默认处理,防止崩溃
        };

        const handleError = (event) => {
            console.error('全局错误:', event.error);
            event.preventDefault(); // 阻止默认处理,防止崩溃
        };

        window.addEventListener('unhandledrejection', handleUnhandledRejection);
        window.addEventListener('error', handleError);

        return () => {
            window.removeEventListener('unhandledrejection', handleUnhandledRejection);
            window.removeEventListener('error', handleError);
        };
    }, []);

    // ...
}

效果:

  • 捕获所有未处理的 Promise rejection如 AxiosError
  • 记录错误到控制台便于调试
  • 阻止应用崩溃和黑屏

4. 在 Auth Layout 添加 ErrorBoundary ✓

文件: src/layouts/Auth.js

修复: 为认证路由添加独立的错误边界

export default function Auth() {
  return (
    <ErrorBoundary>  {/* ✅ Auth 专属错误边界 */}
      <Box minH="100vh">
        <Routes>
          {/* ... 路由配置 */}
        </Routes>
      </Box>
    </ErrorBoundary>
  );
}

效果: 认证页面的错误不会影响整个应用


5. 恢复 WechatRegister 错误提示 ✓

文件: src/components/Auth/WechatRegister.js

问题: Toast 错误提示被注释,用户无法看到错误原因

修复:

} catch (error) {
    console.error('获取微信授权失败:', error);
    toast({  // ✅ 恢复 Toast 提示
        title: "获取微信授权失败",
        description: error.response?.data?.error || error.message || "请稍后重试",
        status: "error",
        duration: 3000,
    });
}

🛡️ 完整错误保护体系

现在系统有四层错误保护

┌─────────────────────────────────────────────────┐
│  第1层: 组件级 try-catch                         │
│  • WechatRegister.getWechatQRCode()            │
│  • SignIn.openWechatLogin()                    │
│  • 显示 Toast 错误提示                          │
└─────────────────────────────────────────────────┘
                      ↓ 未捕获的错误
┌─────────────────────────────────────────────────┐
│  第2层: 页面级 ErrorBoundary (Auth.js)          │
│  • 捕获认证页面的 React 错误                     │
│  • 显示错误页面 + 重载按钮                       │
└─────────────────────────────────────────────────┘
                      ↓ 未捕获的错误
┌─────────────────────────────────────────────────┐
│  第3层: 全局 ErrorBoundary (App.js)             │
│  • 捕获所有 React 组件错误                       │
│  • 最后的防线,防止白屏                          │
└─────────────────────────────────────────────────┘
                      ↓ 异步错误
┌─────────────────────────────────────────────────┐
│  第4层: 全局 Promise Rejection 处理 (App.js)    │
│  • 捕获所有未处理的 Promise rejection            │
│  • 记录到控制台,阻止应用崩溃                     │
└─────────────────────────────────────────────────┘

📊 修复前 vs 修复后

场景 修复前 修复后
API 请求失败 黑屏 Toast 提示 + 页面正常
组件渲染错误 黑屏 错误页面 + 重载按钮
Promise rejection 黑屏 控制台日志 + 页面正常
用户体验 极差(无法恢复) 优秀(可继续操作)

🧪 测试验证

测试场景 1: API 请求失败

操作: 点击"获取二维码",后端返回错误
预期:
✅ 显示 Toast 错误提示
✅ 页面保持正常显示
✅ 可以重新点击按钮

测试场景 2: 网络错误

操作: 断网状态下点击"获取二维码"
预期:
✅ 显示网络错误提示
✅ 页面不黑屏
✅ 控制台记录 AxiosError

测试场景 3: 组件渲染错误

操作: 人为制造组件错误(如访问 undefined 属性)
预期:
✅ ErrorBoundary 捕获错误
✅ 显示错误页面和"重新加载"按钮
✅ 点击按钮可恢复

🔍 调试指南

查看错误日志

打开浏览器开发者工具 (F12),查看 Console 面板:

  1. 组件级错误:

    ❌ 获取微信授权失败: AxiosError {...}
    
  2. Promise rejection:

    ❌ 未捕获的 Promise rejection: Error: Network Error
    
  3. 全局错误:

    ❌ 全局错误: TypeError: Cannot read property 'xxx' of undefined
    

检查 ErrorBoundary 是否生效

  1. 在开发模式下React 会显示错误详情 overlay
  2. 关闭 overlay 后,应该看到 ErrorBoundary 的错误页面
  3. 生产模式下直接显示 ErrorBoundary 错误页面

📝 修改文件清单

文件 修改内容 状态
src/components/ErrorBoundary.js 添加 export default
src/App.js 添加 ErrorBoundary + Promise rejection 处理
src/layouts/Auth.js 添加 ErrorBoundary
src/components/Auth/WechatRegister.js 恢复 Toast 错误提示

⚠️ 注意事项

开发环境 vs 生产环境

开发环境:

  • React 会显示红色错误 overlay
  • ErrorBoundary 的错误详情会显示
  • 控制台有完整的错误堆栈

生产环境:

  • 不显示错误 overlay
  • 直接显示 ErrorBoundary 的用户友好页面
  • 控制台仅记录简化的错误信息

Promise Rejection 处理

  • event.preventDefault() 阻止浏览器默认行为(控制台红色错误)
  • 但错误仍会被记录到 console.error
  • 应用不会崩溃,用户可继续操作

🎯 后续优化建议

1. 添加错误上报服务(可选)

集成 Sentry 或其他错误监控服务:

import * as Sentry from "@sentry/react";

// 在 index.js 初始化
Sentry.init({
  dsn: "YOUR_SENTRY_DSN",
  environment: process.env.NODE_ENV,
});

2. 改进用户体验

  • 为不同类型的错误显示不同的图标和文案
  • 添加"联系客服"按钮
  • 提供常见问题解答链接

3. 优化错误恢复

  • 实现细粒度的错误边界(特定功能区域)
  • 提供局部重试而不是刷新整个页面
  • 缓存用户输入,错误恢复后自动填充

📈 技术细节

ErrorBoundary 原理

class ErrorBoundary extends React.Component {
  componentDidCatch(error, errorInfo) {
    // 捕获子组件树中的所有错误
    // 但无法捕获:
    // 1. 事件处理器中的错误
    // 2. 异步代码中的错误 (setTimeout, Promise)
    // 3. ErrorBoundary 自身的错误
  }
}

Promise Rejection 处理原理

window.addEventListener('unhandledrejection', (event) => {
  // event.reason 包含 Promise rejection 的原因
  // event.promise 是被 reject 的 Promise
  event.preventDefault(); // 阻止默认行为
});

🎉 总结

修复成果

彻底解决黑屏问题

  • API 请求失败不再导致崩溃
  • 用户可以看到清晰的错误提示
  • 页面可以正常继续使用

建立完整错误处理体系

  • 4 层错误保护机制
  • 覆盖同步和异步错误
  • 开发和生产环境都适用

提升用户体验

  • 从"黑屏崩溃"到"友好提示"
  • 提供错误恢复途径
  • 便于问题排查和调试

修复完成时间: 2025-10-14 修复者: Claude Code 版本: 3.0.0