Error Boundaries--React中的錯誤捕獲和上報

錯誤邊界介紹

部分 UI 中的 JavaScript 錯誤不應該破壞整個應用程序涤浇。 為了解決 React 用戶的這個問題燃观,React 16引入了一個 “錯誤邊界(Error Boundaries)” 的新概念铅协。
錯誤邊界是 React 組件,它可以在子組件樹的任何位置捕獲 JavaScript 錯誤,記錄這些錯誤,并顯示一個備用 UI 割坠,而不是使整個組件樹崩潰。 錯誤邊界(Error Boundaries) 在渲染妒牙,生命周期方法以及整個組件樹下的構造函數(shù)中捕獲錯誤彼哼。

使用方法

如果一個類組件定義了生命周期方法中的任何一個(或兩個)static getDerivedStateFromError()componentDidCatch(),那么它就成了一個錯誤邊界湘今。 使用static getDerivedStateFromError()在拋出錯誤后渲染回退UI敢朱。 使用 componentDidCatch() 來記錄錯誤信息。

捕獲范圍

組件內(nèi)異常,也就是異常邊界組件能夠捕獲的異常拴签,主要包括:

  1. 渲染過程中異常孝常;
  2. 生命周期方法中的異常;
  3. 子組件樹中各組件的constructor構造函數(shù)中異常蚓哩。

不能捕獲的異常构灸,主要是異步及服務端觸發(fā)異常:

  1. 事件處理器中的異常;
    處理方法: 使用try/catch代碼進行捕獲
  2. 異步任務異常杖剪,如setTiemout冻押,ajax請求異常等;
    處理方法:使用全局事件window.addEventListener捕獲
  3. 服務端渲染異常盛嘿;
  4. 異常邊界組件自身內(nèi)的異常洛巢;
    處理方法:將邊界組件和業(yè)務組件分離,各司其職次兆,不能在邊界組件中處理邏輯代碼稿茉,也不能在業(yè)務組件中使用didcatch

錯誤邊界盡可以捕獲其子組件的錯誤,無法捕獲其自身的錯誤芥炭;如果一個錯誤邊界無法渲染錯誤信息漓库,則錯誤會向上冒泡至最接近的錯誤邊界。這也類似于 JavaScript 中 catch {} 的工作機制

如何放置錯誤邊界

錯誤邊界的粒度完全取決于你的應用园蝠。你可以將其包裝在最頂層的路由組件并為用戶展示一個 “發(fā)生異常(Something went wrong)“的錯誤信息渺蒿,就像服務端框架通常處理崩潰一樣。你也可以將單獨的插件包裝在錯誤邊界內(nèi)部以保護應用不受該組件崩潰的影響彪薛。

借鑒Facebook的message項目茂装,他們應用錯誤邊界的方式是將大的模塊應用錯誤邊界包裹,這樣當一個主要模塊因為意外的錯誤崩潰后善延,其它組件仍然能夠正常交互

錯誤邊界實戰(zhàn)

首先我定義了一個高階組件

import React from 'react'

const ErrorBoundary = errorInfo => WrapComponent => {
    return class ErrorBoundary extends React.Component{
        constructor(props) {
            super(props);
            this.state = { hasError: false };
        }
        // 這個靜態(tài)方法和componentDidCatch方法定義一個即可
        static getDerivedStateFromError(error) {
            // 當發(fā)生錯誤時少态,設置hasError為true,然后展示自己的錯誤提示組件
            return { hasError: true };
        }

        componentDidCatch(error, info) {
            // 這里可以將報錯信息上報給自己的服務
            // logErrorToMyService(error, info);
        }

        render() {
            if (this.state.hasError) {
                return <h1>{errorInfo}</h1>;
            }
            return <WrapComponent/>;
        }
    }
}
export default ErrorBoundary

接下來可以使用邊界組件包裹業(yè)務組件易遣,這里列舉我認為react項目中可以處理的錯誤方式彼妻,例如事件處理器的錯誤,異步錯誤豆茫,promise錯誤侨歉,渲染錯誤等

import React from 'react'
import ErrorBoundary from '../../utils/ErrorBoundary'
@ErrorBoundary('i am not ok')
export default class Error extends React.Component{
    constructor() {
        super()
    }
    componentWillMount() {
        window.addEventListener('error', event => {
            console.log(event)
        }, true)
        window.addEventListener('unhandledrejection', event => {
            console.log(event)
        })
    }
    // 這個異步錯誤 ErrorBoundary組件不會捕獲到 但是在入口寫的全局window.onerror事件捕獲到了
    componentDidMount() {
        setTimeout(() => {
            // console.log(b)
        }, 100)
    }
    // 事件處理器中的錯誤 onerror也可以捕獲到
    // 這里如果想要hold住錯誤 需要使用try catch
    handleEventError = () => {
        console.log(error)
    }
    // promise 如果reject 但是沒有寫catch語句的話 會報錯 
    // 但是onerror和try-catch和ErrorBoundary組件都無法捕獲
    // 需要寫一個全局unhandledrejection 事件捕獲
    handlePromiseError = () => {
        const promise = new Promise((resolve, reject) => {
            reject()
        })
        promise.then()
    }
    render() {
        return <div>
            <div>hi i am fine</div>
            <button onClick={this.handleEventError}>handle event error</button>
            <button onClick={this.handlePromiseError}>handle promise error</button>
        </div>
    }
}
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市澜薄,隨后出現(xiàn)的幾起案子为肮,更是在濱河造成了極大的恐慌,老刑警劉巖肤京,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異基跑,居然都是意外死亡吗讶,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進店門息楔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來妒峦,“玉大人重斑,你說我怎么就攤上這事】虾В” “怎么了窥浪?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長笛丙。 經(jīng)常有香客問我漾脂,道長,這世上最難降的妖魔是什么胚鸯? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任骨稿,我火速辦了婚禮,結果婚禮上姜钳,老公的妹妹穿的比我還像新娘坦冠。我一直安慰自己,他們只是感情好哥桥,可當我...
    茶點故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布辙浑。 她就那樣靜靜地躺著,像睡著了一般拟糕。 火紅的嫁衣襯著肌膚如雪判呕。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天已卸,我揣著相機與錄音佛玄,去河邊找鬼。 笑死累澡,一個胖子當著我的面吹牛梦抢,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播愧哟,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼奥吩,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蕊梧?” 一聲冷哼從身側響起霞赫,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎肥矢,沒想到半個月后端衰,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體叠洗,經(jīng)...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年旅东,在試婚紗的時候發(fā)現(xiàn)自己被綠了灭抑。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,646評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡抵代,死狀恐怖腾节,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情荤牍,我是刑警寧澤案腺,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站康吵,受9級特大地震影響劈榨,放射性物質發(fā)生泄漏。R本人自食惡果不足惜涎才,卻給世界環(huán)境...
    茶點故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一鞋既、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧耍铜,春花似錦邑闺、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至伴挚,卻和暖如春靶衍,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背茎芋。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工颅眶, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人田弥。 一個月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓涛酗,卻偏偏與公主長得像,于是被迫代替她去往敵國和親偷厦。 傳聞我的和親對象是個殘疾皇子商叹,可洞房花燭夜當晚...
    茶點故事閱讀 43,514評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 1、通過CocoaPods安裝項目名稱項目信息 AFNetworking網(wǎng)絡請求組件 FMDB本地數(shù)據(jù)庫組件 SD...
    陽明先生_X自主閱讀 15,969評論 3 119
  • 今日和企劃部商討品宣包裝只泼,細化三四月份的營銷方案剖笙。品牌定位品牌理念不清晰,營銷動作就沒有主打方向请唱,沒法聚焦弥咪,就沒法...
    一世驚鴻閱讀 76評論 0 0