美文网首页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

    详细的介绍请看这里部分 UI 的异常不应该破坏了整个应用。为了解决 React 用户的这一问题,React 16 ...

  • RN-逻辑崩溃处理:react-native-exception

    和 componentDidCatch 配合使用,页面崩溃处理 + 逻辑崩溃处理,防止大部分的崩溃~

  • RN-可拖动的悬浮按钮

    RN-可拖动的悬浮按钮 需求 分享悬浮按钮,需要展示在特定页面,并且支持拖动(防止遮挡页面内容) 解决方案思路 1...

  • react16新特性

    1. 用 Error Boundary 处理错误 react 组件类中新增了一个componentDidCatch...

  • 异常处理

    componentDidCatch + sentry

  • React权限高阶组件

    权限设置 背景 项目中,设置权限通常有二种 菜单级权限页面级权限 菜单级设置相对简单,可以在统一入口中处理。页面级...

  • 心绪

    崩溃的页面,崩溃的心

  • 可用性指南5.9:处理首页面板宽度

    可用性指南:可访问性 5.9:处理首页面板宽度 相关重要指数:2级 证据强度:3级 文件类型:指南 主题: 页面结...

  • iOS刷新

    tableview或者collectionview添加刷新时,切记不要用点语法,不然程序再页面返回上一级时会崩溃,...

  • Linux开发之崩溃处理

    Linux开发之崩溃处理 注册信号的处理函数EnableCrashHandler 崩溃处理函数OnCrashHan...

网友评论

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

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