RN知识RN 项目使用组件

RN-页面级崩溃处理:componentDidCatch

2018-12-22  本文已影响55人  精神病患者link常

详细的介绍请看这里
部分 UI 的异常不应该破坏了整个应用。为了解决 React 用户的这一问题,React 16 引入了一种称为 “错误边界” 的新概念。 错误边界是用于捕获其子组件树 JavaScript 异常,记录错误并展示一个回退的 UI 的 React 组件,而不是整个组件树的异常。错误组件在渲染期间,生命周期方法内,以及整个组件树构造函数内捕获错误。

⚠️⚠️⚠️⚠️⚠️

  • 事件处理 (比如调用了一个不存在的方法this.abc(),并不会执行componentDidCatch)
  • 异步代码 (例如 setTimeoutrequestAnimationFrame 回调函数)
  • 服务端渲染
  • 错误边界自身抛出来的错误 (而不是其子组件)

⚠️⚠️⚠️⚠️⚠️当render()函数出现问题时,componentDidCatch会捕获异常并处理

此时,render()函数里面发生错误,则 componentDidCatch 会进行调用,在里面进行相应的处理
render() {
  let a = [1,2,3]
  let value = a[3].toString()   对 undefined 进行操作
  return (......)
}

防止 页面 级别的崩溃~

防止 页面 级别的崩溃~

防止 页面 级别的崩溃~

使用方式一:组件方式

/*
* 当做组件使用
* */

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(){
        let newCount = this.state.count + 1
        this.setState({
            count: newCount
        },()=>{
            if (this.state.count == 5){
                throw new Error('i crashed!!!')
            }
        })
    }
    render() {
        // let a = [1,2,3]
        // let value = a[3].toString()
        return (
            <ErrorBoundary>
                <View style={styles.container}>
                    <TouchableOpacity onPress={this.onPress}>
                        <Text>点击我,第5次就崩溃啦</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 {

        constructor(props){
            super(props)
            this.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 {
    constructor(props) {
        super(props);

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

    onPress(){
        let newCount = this.state.count + 1
        this.setState({
            count: newCount
        },()=>{
            if (this.state.count == 5){
                throw new Error('i crashed!!!')
            }
        })
    }
    render() {

        // let a = [1,2,3]
        // let value = a[3].toString()

        return (
            <View style={styles.container}>
                <TouchableOpacity onPress={this.onPress}>
                    <Text>点击我,第5次就崩溃啦</Text>
                </TouchableOpacity>
                <Text style={styles.text}>正常页面显示</Text>
            </View>

        )
    }
}

推荐使用高阶组件方式~

上一篇 下一篇

猜你喜欢

热点阅读