cheungseol / cheungseol.github.io

2 stars 0 forks source link

[React] version 16 Error Handling #14

Open cheungseol opened 6 years ago

cheungseol commented 6 years ago

昨天React 16正式版本发布。

为了使得整个应用不至于因为 UI 的原因崩溃,React 16 引入了error boundary 的新概念。

错误边界 Error boundaries 首先是一个普通的 React 组件,只不过它可以用来捕获发生在子组件树中的错误,能够记录错误,也能让方便地让开发者设计当错误发生时要展示给用户的界面。

componentDidCatch

React v16组件生命周期中提供了一个新的钩子 componentDidCatch,这个方法能够处理 Error boundaries 父组件 wrap 的所有子组件抛出的错误,并且不需要 unmounting 整个app。

注意

Error boundaries 父组件只能捕获自身子组件(存在于自己的子组件树中的组件)抛出的错误。它无法捕获自己抛出的异常。 render 方法中的错误也没法catch。

demo

ErrorBoundary 文件

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

    componentDidCatch(error, info) {
        this.setState({
            hasError: true,
        });
    }

    render() {
        if (this.state.hasError) {
            return (
                <div>
                    {'something bad happened'}
                </div>
            );
        }
        return this.props.children;
    }
}

引入 ErrorBoundary

import {render} from 'react-dom';
import React, {Component} from 'react';
import {connect} from 'react-redux';
import {Provider} from 'react-redux';
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import ErrorBoundary from '../components/ErrorBoundary';
import configureStore from '../store/configureStore';
import * as actions from '../actions';
....

class AppRouter extends Component {
    render() {
        return (
            <Router>
                    <ErrorBoundary>
                        {
                                <div className="app-right">
                                    <Route exact path="/" component={Test}/>
                                </div>
                        }
                    </ErrorBoundary>
            </Router>
        );
    }
}

export default connect(state=>({
   ...
}), actions)(AppRouter);

当 ErrorBoundary 的 Test 子组件中发生错误时, 会被 ErrorBoundary 的 componentDidCatch 方法catch 住

import React, {Component} from 'react'; import ReactDom from 'react-dom'; import {connect} from 'react-redux'; import * as actions from '.actions';

class Test extends Component { constructor() { super(); }

componentDidMount() {
    cosnole.log(a.b)    //  **_运行到这里将抛出一个错误, a is not defined_**
}

render() {
    return (
        <div>
            .....
        </div>
    );
}

}

export default connect(state=>({ ... }), actions)(Test);

参考

Error Handling in React 16

Error Handling using Error Boundaries in React 16