Featured image of post 具有错误边界的强大前端异常管理Featured image of post 具有错误边界的强大前端异常管理

具有错误边界的强大前端异常管理

在运行时失败时实现回退渲染状态,并将崩溃详细信息清晰地记录到日志 Webhook 中。

为什么误差边界很重要

在 React 应用程序中,组件中一个未捕获的 JavaScript 错误可能会导致整个 UI 崩溃。在错误边界之前,这意味着用户会看到一个白屏,没有任何错误提示。错误边界是 React 组件,可以捕获子组件树中任何位置的 JavaScript 错误,并呈现后备 UI,而不是崩溃。

实现误差边界

错误边界是实现静态生命周期方法 getDerivedStateFromErrorcomponentDidCatch 之一或两者的类组件:

import React, { Component, ErrorInfo, ReactNode } from "react";

interface Props {
  children: ReactNode;
  fallback?: ReactNode;
}

interface State {
  hasError: boolean;
  error: Error | null;
}

class ErrorBoundary extends Component<Props, State> {
  constructor(props: Props) {
    super(props);
    this.state = { hasError: false, error: null };
  }

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

  componentDidCatch(error: Error, info: ErrorInfo) {
    console.error("Error caught:", error, info.componentStack);
    // Send to logging service
    logErrorToService(error, info);
  }

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

后备 UI 设计

良好的后备 UI 提供恢复选项并减少用户的挫败感:

function DefaultFallback({ error }: { error: Error | null }) {
  return (
    <div role="alert" className="error-boundary-fallback">
      <h2>Something went wrong</h2>
      <p>We encountered an unexpected error. Please try refreshing the page.</p>
      <button onClick={() => window.location.reload()}>
        Refresh Page
      </button>
      {process.env.NODE_ENV === "development" && (
        <pre>{error?.message}</pre>
      )}
    </div>
  );
}

与日志服务集成 (Sentry)

错误边界与 Sentry 等错误监控工具自然集成:

import * as Sentry from "@sentry/react";

class SentryErrorBoundary extends Component<Props, State> {
  componentDidCatch(error: Error, info: ErrorInfo) {
    Sentry.withScope((scope) => {
      scope.setExtras({ componentStack: info.componentStack });
      Sentry.captureException(error);
    });
  }
}

Sentry 还提供了一个内置的错误边界包装器:

<Sentry.ErrorBoundary fallback={<ErrorFallback />}>
  <App />
</Sentry.ErrorBoundary>

边界放置策略

错误边界的战略布局至关重要:

App
├── ErrorBoundary (global fallback)
│   ├── Layout
│   │   ├── Header
│   │   ├── ErrorBoundary (content area fallback)
│   │   │   ├── MainContent
│   │   │   └── DataTable
│   │   └── Footer
│   └── ErrorBoundary (sidebar fallback)
│       └── SidebarWidget

指南:

  • 独立包装每个主要部分(侧边栏、主要内容、模式)
  • 仅将根边界用作最后的手段
  • 将边界放置在故障可恢复的特征边界处
  • 允许 UI 的正常部分保持功能

错误恢复模式

除了显示回退之外,错误边界还可以提供恢复:

class RecoverableBoundary extends Component {
  state = { hasError: false, error: null };

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

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

  render() {
    if (this.state.hasError) {
      return (
        <div>
          <p>Error: {this.state.error?.message}</p>
          <button onClick={this.handleRetry}>Retry</button>
        </div>
      );
    }
    return this.props.children;
  }
}

局限性

误差边界有需要理解的重要限制:

限制说明
事件处理程序onClick 等中的错误不会被捕获 - 使用 try-catch
异步代码setTimeoutPromise 错误未被捕获
固态继电器错误边界不会捕获服务器端错误
自己的错误错误边界无法捕获其自身的错误
状态突变并非旨在处理损坏的全局状态

结论

错误边界是生产 React 应用程序的重要组成部分。它们可以防止 UI 完全崩溃,提供优雅的降级,并与日志记录服务无缝集成。通过将战略边界放置与正确的错误日志记录和恢复模式相结合,您可以构建能够优雅地处理故障并为开发人员提供可操作诊断的应用程序。