React和React Native页面级崩溃处理:componentDidCatch(错误边界)

1,406 阅读1分钟

部分 UI 的 JavaScript 错误不应该导致整个应用崩溃,为了解决这个问题,React 16 引入了一个新的概念 —— 错误边界。

错误边界是一种 React 组件,这种组件可以捕获发生在其子组件树任何位置的 JavaScript 错误,并打印这些错误,同时展示降级 UI,而并不会渲染那些发生崩溃的子组件树。错误边界在渲染期间、生命周期方法和整个组件树的构造函数中捕获错误。

这里用rn举例一下具体用法

使用方式一:组件方式

class ErrorBoundary extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            error: null,
        };
    }

    componentDidCatch(error, info) {
        alert('1111')
        this.setState({
            error
        });

        // 设置崩溃以后显示的UI
        // 上传错误日志
    }

    render() {

        if (this.state.error) { // 如果页面崩溃,则显示下面的UI
            return (
                <View style={{justifyContent: 'center', alignItems: 'center'}}>
                    <Text style={{color: 'red'}}>
                        {this.state.error && this.state.error.toString()}
                    </Text>

                </View>
            );
        }
        return this.props.children;
    }
}
class RNTestPage extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            count: 0
        }
        this.onPress = this.onPress.bind(this);
    }

    onPress(){
                throw new Error('这个应用崩溃了!!!')
    }
    render() {
        return (
            <ErrorBoundary>
                <View style={styles.container}>
                    <TouchableOpacity onPress={this.onPress}>
                        <Text>点击我就崩溃啦</Text>
                    </TouchableOpacity>
                    <Text style={styles.text}>这里是正常显示的页面</Text>
                </View>
            </ErrorBoundary>


        )
    }
}
export default class RNTest extends React.Component {

    render() {
        return (
            <ErrorBoundary>
              <RNTestPage />
            </ErrorBoundary>


        )
    }
}

使用方式二:高阶组件方式

import React from 'react'
import {
    View,
    Text
} from 'react-native'

function getDisplayName(WrappedComponent) {
    return WrappedComponent.displayName || WrappedComponent.name || 'Component';
}

export default (WrappedComponent)=> {

    class Component extends React.Component {

       
        state = {
                error: new Error(),
                hasError: false // UI级代码是否崩溃
            }
        

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

        render() {
           if (this.state.hasError){
               return <View>
                   <Text>
                       {this.state.error.toString()}
                   </Text>
               </View>
           }
            return <WrappedComponent {...this.props}/>
        }
    }

    Component.displayName = `HOC(${getDisplayName(WrappedComponent)})`;

    return Component
}

使用

/*
* 高阶组件方式使用
* */

@HocErrorCatch
export default class RNTestPage extends React.Component {
    

    onPress(){
                throw new Error('这个应用崩溃了!!!')
            }
        
    
    render() {

        return (
            <View style={styles.container}>
                <TouchableOpacity onPress={this.onPress}>
                    <Text>点击我就崩溃啦</Text>
                </TouchableOpacity>
                <Text style={styles.text}>这里是正常显示的页面</Text>
            </View>

        )
    }
}

日常使用更加推荐高阶函数形式