错误边界(Error boundaries)

从react v16开始,引入边界错误概念。

核心API

  1. getDerivedStateFromError
  2. componentDidCatch

1. 目的:某些UI崩溃,不至于整个webapp崩溃

2. 注意⚠️:错误边界无法捕获如下场景的错误

  • 事件处理(了解更多)
  • 异步代码(例如 setTimeoutrequestAnimationFrame 回调函数)
  • 服务端渲染
  • 它自身抛出来的错误(并非它的子组件)

3.编写错误边界组件

import React, { Component } from 'react';interface ErrorBoundaryProps { };interface ErrorBoundaryState {    hasError: boolean;};class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {    constructor(props: ErrorBoundaryProps) {        super(props);        this.state = {            hasError: false        };    }    static getDerivedStateFromError(error: Error) {        // 更新 state 使下一次渲染能够显示降级后的 UI        return { hasError: true };    }    componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {        // 你同样可以将错误日志上报给服务器        console.group();        console.log('ErrorBoundary catch a error:');        console.info('error', error);        console.info('error info', errorInfo);        console.groupEnd()    }    render() {        console.log('component ErrorBoundary render...');        const { children } = this.props;        const { hasError } = this.state;        // return (        //     <>        //         {        //             hasError ? 'Something Wrong' : children        //         }        //     </>        // )        if (hasError) {            return 'Something wrong';        } else {            return children;        }    }}export default ErrorBoundary;

4.编写一个“错误组件”

点击按钮,触发+1,当counter为5时,抛出Error

import React, { Component } from 'react';interface ErrorComponentProps { };interface ErrorComponentState {    counter: number;};class ErrorComponent extends Component<ErrorComponentProps, ErrorComponentState> {    constructor(props: any) {        super(props);        this.state = {            counter: 0        }        this.handleClick = this.handleClick.bind(this);    }    handleClick() {        // 事件处理的错误,ErrorBoundary无法捕捉        // if (this.state.counter === 5) {        //     throw new Error();        // }        this.setState({            counter: this.state.counter + 1        });    }    render() {        console.log('component ErrorComponent render...');        const { counter } = this.state;        const { handleClick } = this;        if (counter === 5) {            throw new Error('counter creashed!');        }        return (            <>                <p>this component will throw Error when the counter equal to 5</p>                <p>counter : {counter}</p>                <button onClick={handleClick}>add</button>            </>        )    }}export default ErrorComponent;

5. 组合

import React from 'react';import ErrorBoundary from './component/ErrorBoundary';import ErrorComponent from './component/ErrorBoundary/ErrorComponent';function App() {  return (    <div className="App">        <ErrorBoundary>          <ErrorComponent />        </ErrorBoundary>    </div>  );}export default App;

6.打包静态资源

> 不再devserver测试的原因是,在cra的配置中,webpack会捕捉Error并显示错误蒙版,不便于看到测试结果

在package.json添加字段"homepage": "."

7. yarn build

8. 找到index.html,测试吧!