美文网首页RN知识RN 项目使用组件
RN-页面级崩溃处理:componentDidCatch

RN-页面级崩溃处理:componentDidCatch

作者: 精神病患者link常 | 来源:发表于2018-12-22 19:56 被阅读55次

    详细的介绍请看这里
    部分 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>
    
            )
        }
    }
    

    推荐使用高阶组件方式~

    相关文章

      网友评论

        本文标题:RN-页面级崩溃处理:componentDidCatch

        本文链接:https://www.haomeiwen.com/subject/ezlwkqtx.html