错误边界处理

引言

在 React 应用中,一个组件的错误不应导致整个应用崩溃。错误边界(Error Boundaries)是 React 提供的错误隔离机制,它能捕获子组件树中的 JavaScript 错误,并显示降级 UI 而非让整个应用白屏。


什么是错误边界?

错误边界是类组件 ,通过实现 getDerivedStateFromError()componentDidCatch() 生命周期方法来捕获子组件的错误。

javascript 复制代码
class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false, error: null };
  }

  static getDerivedStateFromError(error) {
    // 渲染降级 UI
    return { hasError: true };
  }

  componentDidCatch(error, errorInfo) {
    // 记录错误日志
    console.error('捕获错误:', error, errorInfo);
    this.setState({ error });
  }

  render() {
    if (this.state.hasError) {
      return <FallbackUI error={this.state.error} />;
    }
    return this.props.children;
  }
}

核心 API 对比

方法 调用时机 用途 能否访问组件实例
getDerivedStateFromError 渲染阶段 更新 state 显示降级 UI ❌ 静态方法
componentDidCatch 提交阶段 记录错误日志、上报 ✅ 可访问实例

实战:完整的错误边界组件

javascript 复制代码
class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { 
      hasError: false, 
      error: null,
      errorInfo: null
    };
  }

  static getDerivedStateFromError(error) {
    return { hasError: true };
  }

  componentDidCatch(error, errorInfo) {
    this.setState({ error, errorInfo });
    
    // 上报到错误监控平台
    logErrorToService(error, errorInfo);
  }

  handleRetry = () => {
    this.setState({ hasError: false, error: null, errorInfo: null });
  };

  render() {
    if (this.state.hasError) {
      return (
        <div className="error-boundary">
          <h2>😕 出错了</h2>
          <p>组件渲染失败,请尝试刷新</p>
          <button onClick={this.handleRetry}>重试</button>
          {process.env.NODE_ENV === 'development' && (
            <details>
              <summary>错误详情</summary>
              <pre>{this.state.error?.toString()}</pre>
            </details>
          )}
        </div>
      );
    }
    return this.props.children;
  }
}

错误上报策略

javascript 复制代码
// 错误上报服务
async function logErrorToService(error, errorInfo) {
  const errorData = {
    message: error.message,
    stack: error.stack,
    componentStack: errorInfo.componentStack,
    url: window.location.href,
    userAgent: navigator.userAgent,
    timestamp: Date.now()
  };

  // 使用 sendBeacon 确保上报成功
  navigator.sendBeacon('/api/log-error', JSON.stringify(errorData));
  
  // 或发送到第三方监控平台
  // Sentry.captureException(error, { contexts: { react: errorInfo } });
}

使用场景

javascript 复制代码
// ✅ 包裹可能出错的子组件
<ErrorBoundary>
  <UserProfile userId={123} />
</ErrorBoundary>

// ✅ 多个独立边界,隔离错误
<ErrorBoundary fallback={<ChatFallback />}>
  <ChatWidget />
</ErrorBoundary>

<ErrorBoundary fallback={<FeedFallback />}>
  <NewsFeed />
</ErrorBoundary>

// ❌ 不要包裹整个应用(失去隔离意义)
<ErrorBoundary>
  <App />
</ErrorBoundary>

注意事项

能捕获 不能捕获
子组件渲染错误 事件处理器中的错误
生命周期错误 异步代码(setTimeout、requestAnimationFrame)
构造函数错误 SSR 服务端错误
边界组件自身的错误

总结

  1. 错误边界必须是类组件(Hooks 方案需用第三方库如 react-error-boundary)
  2. 精细化包裹:在可能出错的组件周围单独设置边界
  3. 优雅降级:提供友好的错误提示和重试机制
  4. 错误上报:记录错误信息用于后续分析修复
  5. 开发环境:显示详细错误信息便于调试
相关推荐
a1117767 分钟前
3D 脑图谱 / Bilingual 3D Brain Atlas 项目
前端
T1mzhou15 分钟前
ARM64 Linux 6.10内核启动流程2-rootfs 怎么挂上
linux·服务器·前端
小小尚@1 小时前
WebGIS/ECharts 地图开发|MapLand 在线行政区划边界一键下载 GeoJSON 工具
前端·javascript·echarts
默_笙2 小时前
🚍 一条 Todo 的奇幻漂流:TypeScript 全栈类型安全的"护照检查"
前端·javascript
计算机魔术师2 小时前
NVIDIA 以 129.3 亿美元收购 Hugging Face
前端
平头哥技术团队2 小时前
Day 01 | 用 HTML 写第一个网页:双击就能在浏览器打开
前端
计算机魔术师3 小时前
两年翻45倍!英伟达靠买买买建成千亿投资帝国
前端
paopaokaka_luck3 小时前
基于springboot3+vue3的精准扶贫管理系统(AI 问答、ECharts 图形化分析)
前端·人工智能·echarts
l1m0_3 小时前
智能电动自行车管理后台实战:AI生成页面与React组件化技巧
前端·react.js·ui·ai·设计
Patrick_Wilson4 小时前
为什么gitlab的MR会默认有一个merge commit
前端·git·gitlab