React 错误边界详解

React 错误边界

React错误边界的本质上是防止子组件错误(渲染过程中)向上冒泡导致整个应用崩溃,错误边界可以解决导致整个应用崩溃问题。

在 React 错误边界中,fallback 确实实现了典型的降级策略:

  1. 理想情况:正常渲染业务组件
  2. 异常情况:当组件崩溃时,降级显示预设的备用 UI(组件降级机制)

降级的具体表现

降级前 (正常状态) 降级后 (错误状态)
完整的业务组件功能 简化的备用界面
复杂交互逻辑 可能只保留基本信息和操作
动态数据展示 静态错误提示
完整用户体验 最小可用性保障
// 正常情况:显示复杂的数据可视化图表
<DataVisualization complexData={data} />

// 降级情况:图表组件崩溃后显示简单的表格数据
<ErrorBoundary 
  fallback={<DataTable basicData={data} />}  // 降级为简单表格
>
  <DataVisualization complexData={data} />
</ErrorBoundary>

降级的实现

import React from 'react';

export default class ErrorBoundary extends React.Component {

    constructor() {
        super();
        this.state = { hasError: false, errInfo: null };
    }

    reset() {
        this.setState({
            hasError: false
        });
    }

    static getDerivedStateFromError(error) {
        // 更新 state 使下一次渲染能够显示降级后的 UI
        return { hasError: true, errInfo: error.toString() };
    }

    componentDidCatch(error, errorInfo) {
        // 可以将错误日志上报给服务器
        // logErrorToMyService(error, errorInfo);
    }

    render() {
        const { hasError, errInfo } = this.state;
        const { fallback, children } = this.props;
        if(hasError) {
            // 如果提供了函数式fallback,传入错误和重置方法
            if(typeof fallback == 'function') {
                return fallback({ hasError, errInfo, resetErrorBoundary: this.reset });
            }
            return fallback || <div>{`组件出错了----->${errInfo}`}</div>
        }
        return children;
    }
}

降级策略的层次

1.完全降级:显示完全不同的备用组件

fallback={<ErrorScreen />}

2.部分降级:显示简化版本的组件

fallback={<SimplifiedComponent />}

3.静默降级:隐藏出错部分不影响其他内容

fallback={null}

4.智能降级:根据错误类型显示不同fallback

fallback={(error) => 
  error.type === 'API_ERROR' 
    ? <NetworkError />
    : <GenericError />
}

降级的时机(捕获范围)

会触发降级的情况(错误边界会捕获)

1.组件渲染期间的错误

function BuggyComponent() {
  // 渲染时抛出错误会被捕获
  throw new Error('Render error');
  return <div>正常内容</div>;
}

2. 生命周期方法中的错误

class BuggyComponent extends React.Component {
  componentDidMount() {
    // 生命周期中的错误会被捕获
    throw new Error('Lifecycle error');
  }
  render() { return <div>内容</div>; }
}

3.构造函数中的错误

class BuggyComponent extends React.Component {
  constructor(props) {
    super(props);
    // 构造函数错误会被捕获
    throw new Error('Constructor error');
  }
  render() { return <div>内容</div>; }
}

4.子组件树中任何上述错误

<ErrorBoundary>
  <Parent>  {/* 即使错误发生在深层子组件也会被捕获 */}
    <Child>
      <GrandChildWithError />
    </Child>
  </Parent>
</ErrorBoundary>

不会触发降级的情况(错误边界不会捕获)

1.事件处理函数中的错误

function Component() {
  const handleClick = () => {
    // 事件处理器错误不会被捕获
    throw new Error('Event handler error');
  };
  return <button onClick={handleClick}>点击</button>;
}

2.异步代码中的错误

useEffect(() => {
  // 异步错误不会被捕获
  setTimeout(() => { throw new Error('Async error') }, 1000);
}, []);

3.错误边界组件自身抛出的错误

class BuggyErrorBoundary extends ErrorBoundary {
  render() {
    // 错误边界自身的错误不会被捕获
    throw new Error('Error boundary itself error');
    return super.render();
  }
}

4.React 事件系统的错误

5.服务端渲染的错误

降级应用场景

1. 数据加载组件

场景:API 数据加载组件

<ErrorBoundary
  fallback={({ resetErrorBoundary }) => (
    <div>
      <p>数据加载失败</p>
      <button onClick={resetErrorBoundary}>重试</button>
    </div>
  )}
>
  <AsyncDataLoader userId={123} />  {/* 可能因API异常崩溃 */}
</ErrorBoundary>

作用:网络请求失败时提供重试机制,而非白屏

2. 路由级页面保护

场景:防止整个路由页面崩溃

function App() {
  return (
    <Router>
      <ErrorBoundary fallback={<PageErrorScreen />}>
        <Switch>
          <Route path="/dashboard" component={Dashboard} />  {/* 复杂仪表板 */}
          <Route path="/editor" component={RichTextEditor} /> {/* 易崩溃的编辑器 */}
        </Switch>
      </ErrorBoundary>
    </Router>
  );
}

作用:单个页面崩溃时显示全屏错误页,仍可通过导航切换其他页面

3. 第三方组件容错

<ErrorBoundary 
  fallback={<DataTable data={rawData} />}  // 降级为表格展示
>
  <ThirdPartyChart data={processedData} />  {/* 可能因数据格式异常崩溃 */}
</ErrorBoundary>

作用:当图表库因数据格式异常崩溃时,自动切换为原始数据表格展示

posted @ 2025-07-25 22:08  HuangBingQuan  阅读(50)  评论(0)    收藏  举报