文章目录

React 错误边界:ErrorBoundary 组件

发布于 2026-04-02 14:16:05 · 浏览 8 次 · 评论 0 条

React 错误边界:ErrorBoundary 组件

React 应用在运行时可能因代码异常导致整个页面崩溃。错误边界(Error Boundary)是一种特殊组件,用于捕获其子组件树中 JavaScript 错误,并显示备用 UI,而不是让整个应用白屏或崩溃。创建一个 ErrorBoundary 组件能显著提升用户体验和应用稳定性


创建基础 ErrorBoundary 组件

  1. 新建一个名为 ErrorBoundary.js 的文件

  2. 导入必要的 React 模块

    import React from 'react';
  3. 定义一个类组件并继承 React.Component

    class ErrorBoundary extends React.Component {
      constructor(props) {
        super(props);
        this.state = { hasError: false };
      }
    }
  4. 实现 static getDerivedStateFromError 方法:该方法在子组件抛出错误后被调用,用于更新状态以触发备用 UI 渲染。

    static getDerivedStateFromError(error) {
      return { hasError: true };
    }
  5. 可选:实现 componentDidCatch 方法:用于记录错误信息(例如上报到监控系统)。

    componentDidCatch(error, errorInfo) {
      console.error("Error caught by boundary:", error, errorInfo);
    }
  6. render 方法中根据状态决定渲染内容

    render() {
      if (this.state.hasError) {
        return <h2>出了点问题,请稍后再试。</h2>;
      }
    
      return this.props.children;
    }
  7. 导出组件

    export default ErrorBoundary;

完整代码如下:

import React from 'react';

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

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

  componentDidCatch(error, errorInfo) {
    console.error("Error caught by boundary:", error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      return <h2>出了点问题,请稍后再试。</h2>;
    }

    return this.props.children;
  }
}

export default ErrorBoundary;

在应用中使用 ErrorBoundary

  1. 在需要保护的组件外层包裹 <ErrorBoundary>。例如,在 App.js 中:

    import React from 'react';
    import ErrorBoundary from './ErrorBoundary';
    import UserProfile from './UserProfile';
    
    function App() {
      return (
        <div>
          <h1>我的应用</h1>
          <ErrorBoundary>
            <UserProfile />
          </ErrorBoundary>
        </div>
      );
    }
    
    export default App;
  2. 确保错误发生在 ErrorBoundary 的子组件内部。注意:错误边界无法捕获以下情况的错误

    • 事件处理函数中的错误
    • 异步代码(如 setTimeoutPromise 回调)
    • 服务端渲染过程中的错误
    • 错误边界自身抛出的错误

自定义错误显示与重置机制

为提升交互体验,可添加“重试”按钮让用户手动恢复界面。

  1. ErrorBoundary 的状态中增加 errorerrorInfo 字段(可选,用于调试):

    constructor(props) {
      super(props);
      this.state = { hasError: false, error: null, errorInfo: null };
    }
  2. 修改 componentDidCatch 以保存错误详情

    componentDidCatch(error, errorInfo) {
      this.setState({
        hasError: true,
        error: error,
        errorInfo: errorInfo
      });
    }
  3. 添加一个重置方法

    handleReset = () => {
      this.setState({ hasError: false, error: null, errorInfo: null });
    };
  4. 在错误 UI 中加入重试按钮

    render() {
      if (this.state.hasError) {
        return (
          <div>
            <h2>出了点问题,请稍后再试。</h2>
            <button onClick={this.handleReset}>重试</button>
          </div>
        );
      }
    
      return this.props.children;
    }

更新后的完整组件:

import React from 'react';

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({
      hasError: true,
      error: error,
      errorInfo: errorInfo
    });
  }

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

  render() {
    if (this.state.hasError) {
      return (
        <div>
          <h2>出了点问题,请稍后再试。</h2>
          <button onClick={this.handleReset}>重试</button>
        </div>
      );
    }

    return this.props.children;
  }
}

export default ErrorBoundary;

注意事项与最佳实践

场景 是否能被捕获 说明
子组件 render 中的错误 错误边界的主要用途
事件处理函数(如 onClick)中的错误 应使用 try/catch 处理
异步回调(如 fetch.then)中的错误 需在异步逻辑内部捕获
useEffect 中的错误 React 16+ 中不会触发错误边界
服务端渲染错误 需在服务器中间件中处理

不要将错误边界包裹整个应用根节点。建议按功能模块划分,例如分别保护导航栏、主内容区、侧边栏等,避免局部错误影响全局。

避免在错误边界中执行复杂逻辑getDerivedStateFromErrorcomponentDidCatch 应保持轻量,防止二次崩溃。

测试错误边界行为:可临时在子组件中加入 throw new Error('Test') 验证备用 UI 是否正常显示。

评论 (0)

暂无评论,快来抢沙发吧!

扫一扫,手机查看

扫描上方二维码,在手机上查看本文