RN-页面级崩溃处理:componentDidCatch

详细的介绍请看这里
部分 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 (
                
                    
                        {this.state.error && this.state.error.toString()}
                    

                
            );
        }
        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 (
            
                
                    
                        点击我,第5次就崩溃啦
                    
                    正常页面显示
                
            


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

    render() {
        return (
            
              
            


        )
    }
}

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

高阶组件


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 
                   
                       {this.state.error.toString()}
                   
               
           }
            return 
        }
    }

    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 (
            
                
                    点击我,第5次就崩溃啦
                
                正常页面显示
            

        )
    }
}

推荐使用高阶组件方式~

你可能感兴趣的:(RN-页面级崩溃处理:componentDidCatch)