错误边界处理

引言

在 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. 开发环境:显示详细错误信息便于调试
相关推荐
咩咩啃树皮6 小时前
第40篇:Vue3组件化开发精讲——组件拆分、复用、父子通信、工程化架构
java·前端·架构
阳光是sunny6 小时前
LangGraph中的Reducer是什么
前端·人工智能·后端
触底反弹6 小时前
一文搞懂 Tailwind CSS 弹性布局:从原理到实战
前端·css·html
阳光是sunny6 小时前
从链到图:LangGraph 入门基础全解析
前端·人工智能·后端
小林ixn7 小时前
从 ??= 到 onKeyDown:一个 React 组件的“自我修养”
前端·javascript·react.js
REDcker7 小时前
显示分辨率标准对照详解
前端·网络·分辨率·显示·屏幕
এ慕ོ冬℘゜8 小时前
前端实战:jQuery 多条件联合搜索(标题模糊查询 + 日历时间段筛选)
前端·javascript·jquery
武子康8 小时前
Search Console Platform Properties 扩大 SEO 资产边界:从 Page Ranking 到 Topic Coverage(5 类误读边界 + 3 表数据层设计)
前端·人工智能·后端
一点一木9 小时前
从60首歌到1个网站:输入你的故事,还你一首歌
前端·github
IT_陈寒10 小时前
Vue这个特性差点让我加班到凌晨,谁懂啊
前端·人工智能·后端