React实战:使用componentDidCatch捕获子组件的错误

2,372 阅读1分钟

如果渲染的子组件不可信(比如来源于第三方),怎么保证程序的正常运行?

本文主要是React生命周期componentDidCatch的应用。

UntrustedComponent.js不可信组件代码如下:

import {useState} from 'react';

export default function UntrustedComponent() {
  const [list, setList] = useState([1,2,3])

  // 为模拟错误,此处故意赋值为null
  function onClick() {
    setList(null)
  }

  return (
    <div>
      <h3>第三方组件</h3>
      <button onClick={onClick}>点击模拟触发错误</button>
      <ul>
        {list.map(item => <li key={item}>{item}</li>)}
      </ul>
    </div>
  )
}

点击模拟触发错误按钮,将会在render期间抛出错误。

App.js未使用componentDidCatch时的代码如下:

import UntrustedComponent from './components/UntrustedComponent';

function App() {
  return (
    <div>
      <h1>我的网站</h1>
      <UntrustedComponent />
    </div>
  );
}

export default App;

此时,当子组件UntrustedComponent组件触发错误时,将导致整个App无法渲染(也就是白屏)。所以当子组件不可信时,应捕获错误,以防整个App都受到影响。

605a00fe46df2736b1a54976.png

ErrorBoundary.js错误捕获组件 如下:

import React from 'react'

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

  static getDerivedStateFromError(error) {
    // 更新 state 使下一次渲染可以显示错误提示
    return { hasError: true };
  }

  componentDidCatch(error, info) {
    // Example "componentStack":
    // at UntrustedComponent
    // at ErrorBoundary
    // at div
    // at App
    console.log(info.componentStack);
  }

  render() {
    if (this.state.hasError) {
      return <div>子组件渲染错误。</div>;
    }

    return this.props.children;
  }
}

App.js使用ErrorBoundary时的代码如下:

import ErrorBoundary from './components/ErrorBoundary';
import UntrustedComponent from './components/UntrustedComponent';

function App() {
  return (
    <div className='app'>
      <h1>我的网站</h1>
      <ErrorBoundary>
        <UntrustedComponent />
      </ErrorBoundary>
    </div>
  );
}

export default App;

此时,当子组件UntrustedComponent组件触发错误时,错误将被捕获,效果如下:

605a014e46df2736b1a54978.png

错误日志如下:

at UntrustedComponent (http://localhost:3001/static/js/main.chunk.js:319:81)
at ErrorBoundary (http://localhost:3001/main.7261ff8cf03a4eb4d481.hot-update.js:25:5)
at div
at App

原文地址

www.hijs.ren/article/blo…