Skip to content

错误边界

错误边界(Error Boundaries)是 React 中用于捕获并处理其子组件树中发生的 JavaScript 错误的特殊组件。它们提供了一种优雅降级的方式,确保即使部分组件抛出错误,整个应用程序也不会崩溃。错误边界可以捕获以及的错误。

创建和使用错误边界

要创建一个错误边界,你需要定义一个继承自 React.Component 的类组件,并实现以下两个生命周期方法之一或两者:

  • componentDidCatch(error, info):当子组件抛出错误时调用,允许你记录错误信息或执行其他清理操作。
  • static getDerivedStateFromError(error):这是一个静态方法,当子组件抛出错误时调用,可以用来更新组件的状态以展示备用 UI。

示例代码

jsx
import React, { Component } from "react";

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

  static getDerivedStateFromError(error) {
    // 更新 state 以便下一次渲染可以显示降级后的 UI
    return { hasError: true };
  }

  componentDidCatch(error, info) {
    // 你可以在这里记录错误信息到外部监控系统
    console.error("Caught an error:", error, info.componentStack);
  }

  render() {
    if (this.state.hasError) {
      // 你可以自定义降级后的 UI 并渲染它
      return <h1>Something went wrong.</h1>;
    }

    // 正常情况下渲染子组件
    return this.props.children;
  }
}

export default ErrorBoundary;

使用错误边界

要使用错误边界,只需将它包裹在你想要保护的组件周围即可:

jsx
<ErrorBoundary>
  <MyComponent />
</ErrorBoundary>

错误边界的工作原理

  1. 捕获错误:当子组件树中的任何地方发生错误时,错误边界会捕获这个错误,并阻止它传播到更高级别的组件。
  2. 显示备用 UI:通过设置组件的状态(例如 hasError: true),错误边界可以在捕获错误后显示备用用户界面。
  3. 记录错误信息:利用 componentDidCatch 方法,你可以记录错误信息到日志服务或其他监控系统,以便后续分析和修复。

注意事项

  1. 错误边界仅捕获子组件中的错误

    • 它们不会捕获以下类型的错误:
      • 事件处理器中的错误(例如按钮点击事件)
      • 异步代码中的错误(例如 setTimeoutrequestAnimationFrame 回调)
      • 服务器端渲染期间的错误
      • 错误边界自身的错误
  2. 每个组件树只需要一个错误边界

    • 通常不需要为每个组件都添加错误边界。相反,应该选择性地在整个应用的关键部分使用它们,比如页面级别的组件或复杂的用户交互模块。
  3. 避免过度使用错误边界

    • 过多的错误边界可能会使代码变得复杂且难以维护。合理规划错误边界的使用位置,以保持代码的清晰性和可维护性。
  4. 不要在错误边界内使用 try...catch

    • 在 React 组件中,try...catch 无法捕获渲染阶段的错误。对于这种情况,你应该依赖错误边界来处理。
  5. 辅助功能 (a11y)

    • 当显示错误消息时,请确保遵循无障碍设计的最佳实践,如使用语义化的 HTML 元素 (<article><section> 标签) 和 ARIA 属性,以确保屏幕阅读器和其他辅助技术能够正确解释错误信息。
  6. 日志记录

    • 利用 componentDidCatch 方法记录错误信息到外部日志服务,可以帮助你更好地监控和调试生产环境中的问题。
  7. 错误恢复

    • 错误边界通常用于防止应用程序崩溃,但并不意味着它可以自动恢复错误状态。如果你的应用程序需要某种形式的恢复机制,你可能还需要额外的逻辑来处理这一点。

示例:带有错误边界的完整应用

假设我们有一个简单的应用,其中包含一个可能会随机崩溃的组件 MyComponent。我们将使用 ErrorBoundary 来捕获并处理这个组件的潜在错误。

jsx
import React, { Component } from "react";
import ReactDOM from "react-dom";

// 错误边界组件
class ErrorBoundary extends Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

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

  componentDidCatch(error, info) {
    console.error("Caught an error:", error, info.componentStack);
  }

  render() {
    if (this.state.hasError) {
      return <h1>Something went wrong.</h1>;
    }

    return this.props.children;
  }
}

// 可能会抛出错误的组件
function MyComponent() {
  if (Math.random() > 0.8) {
    throw new Error("I crashed!");
  }
  return <div>Randomly crashes!</div>;
}

// 主应用组件
function App() {
  return (
    <div>
      <h2>Welcome to the app</h2>
      <ErrorBoundary>
        <MyComponent />
      </ErrorBoundary>
    </div>
  );
}

ReactDOM.render(<App />, document.getElementById("root"));

在这个例子中:

  • ErrorBoundary 是一个简单的错误边界组件,它会在子组件抛出错误时显示一条消息。
  • MyComponent 是一个模拟可能随机崩溃的组件。
  • App 组件使用 ErrorBoundary 包裹了 MyComponent,以确保即使 MyComponent 抛出了错误,整个应用程序也不会崩溃。

总结

错误边界是 React 提供的一种强大工具,用于捕获子组件树中的 JavaScript 错误并优雅地处理它们。通过理解如何创建和使用错误边界,你可以构建更加健壮和用户友好的应用程序。

Released under the MIT License.