詳細(xì)的介紹請(qǐng)看這里
部分 UI 的異常不應(yīng)該破壞了整個(gè)應(yīng)用拼坎。為了解決 React 用戶的這一問題,React 16 引入了一種稱為 “錯(cuò)誤邊界” 的新概念稽犁。 錯(cuò)誤邊界是用于捕獲其子組件樹 JavaScript 異常熔号,記錄錯(cuò)誤并展示一個(gè)回退的 UI 的 React 組件依痊,而不是整個(gè)組件樹的異常。錯(cuò)誤組件在渲染期間齐苛,生命周期方法內(nèi)翘盖,以及整個(gè)組件樹構(gòu)造函數(shù)內(nèi)捕獲錯(cuò)誤。
??????????
- 事件處理 (比如調(diào)用了一個(gè)不存在的方法
this.abc()
,并不會(huì)執(zhí)行componentDidCatch
)- 異步代碼 (例如
setTimeout
或requestAnimationFrame
回調(diào)函數(shù))- 服務(wù)端渲染
- 錯(cuò)誤邊界自身拋出來的錯(cuò)誤 (而不是其子組件)
??????????當(dāng)render()函數(shù)出現(xiàn)問題時(shí)凹蜂,componentDidCatch
會(huì)捕獲異常并處理
此時(shí)馍驯,render()函數(shù)里面發(fā)生錯(cuò)誤,則 componentDidCatch 會(huì)進(jìn)行調(diào)用玛痊,在里面進(jìn)行相應(yīng)的處理
render() {
let a = [1,2,3]
let value = a[3].toString() 對(duì) undefined 進(jìn)行操作
return (......)
}
防止 頁(yè)面 級(jí)別的崩潰~
防止 頁(yè)面 級(jí)別的崩潰~
防止 頁(yè)面 級(jí)別的崩潰~
使用方式一:組件方式
/*
* 當(dāng)做組件使用
* */
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = {
error: null,
};
}
componentDidCatch(error, info) {
alert('1111')
this.setState({
error
});
// 設(shè)置崩潰以后顯示的UI
// 上傳錯(cuò)誤日志
}
render() {
if (this.state.error) { // 如果頁(yè)面崩潰汰瘫,則顯示下面的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!G浞取吟吝!')
}
})
}
render() {
// let a = [1,2,3]
// let value = a[3].toString()
return (
<ErrorBoundary>
<View style={styles.container}>
<TouchableOpacity onPress={this.onPress}>
<Text>點(diǎn)擊我菱父,第5次就崩潰啦</Text>
</TouchableOpacity>
<Text style={styles.text}>正常頁(yè)面顯示</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級(jí)代碼是否崩潰
}
}
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>點(diǎn)擊我官辽,第5次就崩潰啦</Text>
</TouchableOpacity>
<Text style={styles.text}>正常頁(yè)面顯示</Text>
</View>
)
}
}
推薦使用高階組件方式~