Skip to content

react错误捕获

React16开始,官方提供ErrorBoundary错误边界,被该组件包裹的子组件render函数报错时会触发离当前组件最近的父组件ErrorBoundary

这种情况下,可以通过componentDidCatch将捕获的错误上报

javascript
import React, { ReactNode } from 'react'
import { lazyReportBatch } from '../common/report'
import {
  getErrorUid,
  getReactComponentInfo,
  parseStackFrames
} from '../common/utils'
import { ReactErrorType } from '../types'
import { TraceSubTypeEnum, TraceTypeEnum } from '../common/enum'
import { getBehaviour, getRecordScreenData } from '../behavior'

interface ErrorBoundaryProps {
  Fallback: ReactNode // ReactNode 表示任意有效的 React 内容
  children: ReactNode
}

interface ErrorBoundaryState {
  hasError: boolean
}

let err = {}

class ErrorBoundary extends React.Component<
  ErrorBoundaryProps,
  ErrorBoundaryState
> {
  state: ErrorBoundaryState = { hasError: false }

  componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
    this.setState({ hasError: true })
    const { componentName, url: src } = getReactComponentInfo(errorInfo)
    const type = TraceTypeEnum.error
    const subType = TraceSubTypeEnum.react
    const message = error.message
    const stack = parseStackFrames(error)
    const pageUrl = window.location.href
    const errId = getErrorUid(`${subType}-${message}-${src}`)
    const info = error.message
    const behavior = getBehaviour()
    const state = behavior?.breadcrumbs?.state || []
    const eventData = getRecordScreenData()
    const reportData: ReactErrorType = {
      type,
      subType,
      stack,
      pageUrl,
      message,
      errId,
      componentName,
      info,
      src,
      state,
      timestamp: new Date().getTime(),
      eventData
    }
    err = reportData
    lazyReportBatch(reportData)
  }

  render() {
    const { Fallback } = this.props    
    if (this.state.hasError) {
      // @ts-ignore
      return <Fallback error={err}/>
    }

    return this.props.children
  }
}

export default ErrorBoundary

Released under the MIT License.