React之錯誤邊界 Error Boundaries示例詳解
引言
過去,組件內(nèi)的代碼異常會導(dǎo)致 React 的內(nèi)部狀態(tài)被破壞,產(chǎn)生可能無法追蹤的錯誤。但 React 并沒有提供一種優(yōu)雅處理這些錯誤的方式,也無法從錯誤中恢復(fù)。
默認(rèn)情況下,若一個組件在渲染期間(render)發(fā)生錯誤,會導(dǎo)致整個組件樹全部被卸載,這當(dāng)然不是我們期望的結(jié)果。
部分組件的錯誤不應(yīng)該導(dǎo)致整個應(yīng)用崩潰。為了解決這個問題,React 16 引入了一個新的概念 —— 錯誤邊界
錯誤邊界是一種 React 組件,這種組件可以捕獲發(fā)生在其子組件樹任何位置的異常,并打印這些錯誤,同時展示降級 UI,而并不會渲染那些發(fā)生崩潰的子組件樹。
注意
- 錯誤邊界目前只在
Class Component
中實現(xiàn)了,沒有在hooks
中實現(xiàn)(因為Error Boundaries的實現(xiàn)借助了this.setState可以傳遞callback的特性,useState無法傳入回調(diào),所以無法完全對標(biāo)); - 錯誤邊界 無法捕獲 以下四種場景中產(chǎn)生的錯誤:
- 事件處理函數(shù)(因為 Error Boundaries 實現(xiàn)的本質(zhì)是觸發(fā)更新,但是事件處理函數(shù)不在render或者commit階段,所以無法進(jìn)行捕獲,如果你需要在事件處理器內(nèi)部捕獲錯誤,可以使用原生的
try
/catch
語句 了解更多) - 異步代碼(例如
setTimeout
或requestAnimationFrame
回調(diào)函數(shù)) - 服務(wù)端渲染(因為觸發(fā)更新只能在客戶端進(jìn)行,不能在serve端進(jìn)行)
- 它自身拋出來的錯誤(因為錯誤拋出要向父節(jié)點冒泡尋找 Error Boundaries 處理,無法處理自身產(chǎn)生的錯誤)
- 事件處理函數(shù)(因為 Error Boundaries 實現(xiàn)的本質(zhì)是觸發(fā)更新,但是事件處理函數(shù)不在render或者commit階段,所以無法進(jìn)行捕獲,如果你需要在事件處理器內(nèi)部捕獲錯誤,可以使用原生的
實現(xiàn)
React中提供了兩個與錯誤處理相關(guān)的api:
getderivedstatefromerror
:靜態(tài)方法,當(dāng)錯誤發(fā)生后,提供一個機(jī)會渲染 Fallback UIcomponentDidCatch
:組件實例方法,當(dāng)錯誤發(fā)生后,提供一個機(jī)會記錄錯誤信息
如果一個 class 組件中定義了 getDerivedStateFromError() 或 componentDidCatch() 這兩個生命周期方法中的任意一個(或兩個)時,那么它就變成一個錯誤邊界。當(dāng)拋出錯誤后,請使用 getDerivedStateFromError()
渲染備用 UI ,使用 componentDidCatch()
打印錯誤信息。
class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false, }; } getDerivedStateFromError(error) { // 更新 state 使下一次渲染能夠顯示降級后的 UI return { hasError: true }; } componentDidCatch(error, errorInfo) { // 你同樣可以將錯誤日志上報給服務(wù)器 logErrorToService(error, errorInfo); } render() { if (this.state.hasError) { // 你可以自定義降級后的 UI 并渲染 return <h1>wrong message</h1>; } return this.props.children; } } export default ErrorBoundary;
然后你可以將它作為一個常規(guī)組件去使用:
<ErrorBoundary> <A /> <B /> <C /> </ErrorBoundary>
錯誤邊界的工作方式類似于原生的 catch {}
,不同的地方在于,錯誤邊界只針對 React 組件。并且只有 class 組件才可以成為錯誤邊界組件。大多數(shù)情況下, 你只需要聲明一次錯誤邊界組件, 并在整個應(yīng)用中使用它。
錯誤邊界應(yīng)該放置在哪?
錯誤邊界的粒度由你來決定,可以將其包裝在最頂層的路由組件中,并為用戶展示一個 “xxx” 的錯誤信息,就像服務(wù)端框架經(jīng)常處理崩潰一樣。也可以將單獨的組件包裝在錯誤邊界,從而保護(hù)其它組件不會崩潰。(例如,F(xiàn)acebook Messenger 將側(cè)邊欄、信息面板、聊天記錄以及信息輸入框包裝在單獨的錯誤邊界中。如果其中的某些 UI 組件崩潰,其余部分仍然能夠交互。)
未捕獲錯誤(Uncaught Errors)該如何處理?
自 React 16 起,任何未被錯誤邊界捕獲的錯誤將會導(dǎo)致整個 React 組件樹被卸載。
在某些場景下,把一個錯誤的 UI 留在那,比完全移除它要更糟糕。比如在類似 Messenger 的產(chǎn)品中,把一個異常的 UI 展示給用戶,可能會導(dǎo)致用戶把錯誤信息發(fā)給別人。同樣,對于支付類場景而言,與其顯示錯誤的支付金額,不如直接讓頁面白屏。
(所以,錯誤邊界的使用難點在于尋找合適的時機(jī)
,知道在什么時候該用
,什么時候不該用
,這是一個充滿哲學(xué)的問題)
注意:自 React 15 的命名更改
React 15 中有一個支持有限的錯誤邊界方法 unstable_handleError
。這個方法不再起作用,自 React 16 起你需要在代碼中將其修改為 componentDidCatch
。
以上就是React之錯誤邊界 Error Boundaries示例詳解的詳細(xì)內(nèi)容,更多關(guān)于React 錯誤邊界的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
在React框架中實現(xiàn)一些AngularJS中ng指令的例子
這篇文章主要介紹了在JavaScript的React框架中實現(xiàn)一些AngularJS指令的例子,React使用Virtual DOM因而與普通的js框架有些不同,需要的朋友可以參考下2016-03-03React中使用Axios發(fā)起POST請求提交文件方式
這篇文章主要介紹了React中使用Axios發(fā)起POST請求提交文件方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-02-02React競態(tài)條件Race Condition實例詳解
這篇文章主要為大家介紹了React競態(tài)條件Race Condition實例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11TS裝飾器bindThis優(yōu)雅實現(xiàn)React類組件中this綁定
這篇文章主要為大家介紹了TS裝飾器bindThis優(yōu)雅實現(xiàn)React類組件中this綁定,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11