乐趣区

react之错误边界Error-Boundaries

错误边界(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,测试吧!

退出移动版