一、概况
JS运行时的异常主要分为以下两种:
a) 逻辑上的JS异常,比如单按钮之后的行为,需要进行计算参数,跳转至另一个page,在计算的过程中出现了异常,但不触发当前component的render。
b) 会影响到当前的render或子component的render出现的错误,即错误出现在render方法中。
二、出错后的现象
a)当在开发模式时,所有的JS异常都会弹出红屏
b)当在Release模式时,JS逻辑上的异常(即1.a的情况),会导致点击按钮无响应,但页面不会卡死或白屏。
c)当在Release模式时,JS在render时触发的异常(即1.b的情况),会导致JS所在的整体ReactView无响应或白屏,包括无法物理键返回等。
三、解决方案
a)针对JS的不同错误错误,都可以通过ErrorHander进行捕获进行异常上报。
b)针对JS的逻辑异常,由于不影响当前页面的渲染,所以当前页面可以在ErrorHandler发送通知根据需要重新render页面或不处理。表现为点了按钮没反应。
c)针对JS的渲染时异常,React16之后增加了异常边界的概念,可以使用componentDidCatch来抓取render中出现的错误,避免js所在的ReactView无响应。
d)使用componentDidCatch时,可以抓取当前被包裹的组件以及子组件的render异常。
e)componentDidCatch抓取render异常后,可以重新设置当前出错页面的state,从而根据需要进行渲染错误页,也不会影响页面本身的其它行为(如物理返回事件),或应用内其它js页面或逻辑的运行。
四、相关代码
a) componentDidCatch使用,需要包裹起来,直接覆写componentDidCatch无效果。另外在DEV模式还是会弹红报错,并且渲染希望的错误页面。
class PotentialError extends Component {
constructor(props) {
super(props);
this.state = {error: false};
}
componentDidCatch(error, info) {
this.setState({error, info});
}
render() {
if (this.state.error) {
return (
<View style={{flex: 1, backgroundColor: 'gray'}}>
<Text>报错啦~~{JSON.stringify(this.state.error)}</Text>
</View>
);
}
return this.props.children;
}
}
render() {
return (
<PotentialError>
<BaseView
title={this.props.header_title}
{this._renderRnList()}
</BaseView>
</PotentialError>
);
}
####五、后续
各业务可以在基于自有的BasePage的基础上利用实现componentDidCatch自定义出错时的页面。或common统一实现错误页面。推荐各业务自己实现错误页面,返回之后其它页面业务逻辑正常运行。