react Error Boundaries

created at 07-07-2021 views: 1

Error boundaries

Starting from react v16, the concept of boundary error has been introduced.

Core API

  1. getDerivedStateFromError
  2. componentDidCatch

1. Purpose

Some UI crashes, so that the entire webapp will not crash

2. Note

The error boundary cannot capture errors in the following scenarios

  • Event handling 
  • Asynchronous code (such as setTimeout or requestAnimationFrame callback function)
  • Server-side rendering
  • Errors thrown by itself (not its child components)

3. Write error boundary components

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) {
        // Update the state so that the next rendering can display the degraded UI
        return { hasError: true };
    }

    componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
        // You can also report the error log to the server
        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. Write an "error component"

Click the button to trigger +1, when the counter is 5, an Error is thrown

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() {
        // Event handling error, ErrorBoundary cannot catch
        // 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. Combination

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. Package static resources

The reason why devserver is no longer tested is that in the cra configuration, webpack will catch Error and display the error mask, which is not easy to see the test results.

Add the field "homepage": "." to package.json

7. yarn build

8. Find index.html and test it!

Please log in to leave a comment.