網站首頁 編程語言 正文
引言
過去,組件內的代碼異常會導致 React 的內部狀態被破壞,產生可能無法追蹤的錯誤。但 React 并沒有提供一種優雅處理這些錯誤的方式,也無法從錯誤中恢復。
默認情況下,若一個組件在渲染期間(render)發生錯誤,會導致整個組件樹全部被卸載,這當然不是我們期望的結果。
部分組件的錯誤不應該導致整個應用崩潰。為了解決這個問題,React 16 引入了一個新的概念 —— 錯誤邊界
錯誤邊界是一種 React 組件,這種組件可以捕獲發生在其子組件樹任何位置的異常,并打印這些錯誤,同時展示降級 UI,而并不會渲染那些發生崩潰的子組件樹。
注意
- 錯誤邊界目前只在
Class Component
中實現了,沒有在hooks
中實現(因為Error Boundaries的實現借助了this.setState可以傳遞callback的特性,useState無法傳入回調,所以無法完全對標); - 錯誤邊界 無法捕獲 以下四種場景中產生的錯誤:
- 事件處理函數(因為 Error Boundaries 實現的本質是觸發更新,但是事件處理函數不在render或者commit階段,所以無法進行捕獲,如果你需要在事件處理器內部捕獲錯誤,可以使用原生的
try
?/?catch
?語句 了解更多) - 異步代碼(例如?
setTimeout
?或?requestAnimationFrame
?回調函數) - 服務端渲染(因為觸發更新只能在客戶端進行,不能在serve端進行)
- 它自身拋出來的錯誤(因為錯誤拋出要向父節點冒泡尋找 Error Boundaries 處理,無法處理自身產生的錯誤)
- 事件處理函數(因為 Error Boundaries 實現的本質是觸發更新,但是事件處理函數不在render或者commit階段,所以無法進行捕獲,如果你需要在事件處理器內部捕獲錯誤,可以使用原生的
實現
React中提供了兩個與錯誤處理相關的api:
-
getderivedstatefromerror
:靜態方法,當錯誤發生后,提供一個機會渲染 Fallback UI -
componentDidCatch
:組件實例方法,當錯誤發生后,提供一個機會記錄錯誤信息
如果一個 class 組件中定義了?getDerivedStateFromError()?或?componentDidCatch()?這兩個生命周期方法中的任意一個(或兩個)時,那么它就變成一個錯誤邊界。當拋出錯誤后,請使用?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) { // 你同樣可以將錯誤日志上報給服務器 logErrorToService(error, errorInfo); } render() { if (this.state.hasError) { // 你可以自定義降級后的 UI 并渲染 return <h1>wrong message</h1>; } return this.props.children; } } export default ErrorBoundary;
然后你可以將它作為一個常規組件去使用:
<ErrorBoundary> <A /> <B /> <C /> </ErrorBoundary>
錯誤邊界的工作方式類似于原生的?catch {}
,不同的地方在于,錯誤邊界只針對 React 組件。并且只有 class 組件才可以成為錯誤邊界組件。大多數情況下, 你只需要聲明一次錯誤邊界組件, 并在整個應用中使用它。
錯誤邊界應該放置在哪?
錯誤邊界的粒度由你來決定,可以將其包裝在最頂層的路由組件中,并為用戶展示一個 “xxx” 的錯誤信息,就像服務端框架經常處理崩潰一樣。也可以將單獨的組件包裝在錯誤邊界,從而保護其它組件不會崩潰。(例如,Facebook Messenger 將側邊欄、信息面板、聊天記錄以及信息輸入框包裝在單獨的錯誤邊界中。如果其中的某些 UI 組件崩潰,其余部分仍然能夠交互。)
未捕獲錯誤(Uncaught Errors)該如何處理?
自 React 16 起,任何未被錯誤邊界捕獲的錯誤將會導致整個 React 組件樹被卸載。
在某些場景下,把一個錯誤的 UI 留在那,比完全移除它要更糟糕。比如在類似 Messenger 的產品中,把一個異常的 UI 展示給用戶,可能會導致用戶把錯誤信息發給別人。同樣,對于支付類場景而言,與其顯示錯誤的支付金額,不如直接讓頁面白屏。
(所以,錯誤邊界的使用難點在于尋找合適的時機
,知道在什么時候該用
,什么時候不該用
,這是一個充滿哲學的問題)
注意:自 React 15 的命名更改
React 15 中有一個支持有限的錯誤邊界方法?unstable_handleError
。這個方法不再起作用,自 React 16 起你需要在代碼中將其修改為?componentDidCatch
。
原文鏈接:https://juejin.cn/post/7040689855205998605
相關推薦
- 2022-06-11 kubernetes實現分布式限流_云和虛擬化
- 2022-07-06 Android中ViewFlipper和AdapterViewFlipper使用的方法實例_Andr
- 2022-05-06 詳解go語言中sort如何排序_Golang
- 2021-12-09 Typora自動編號的具體操作_其它綜合
- 2022-01-03 antd獲取表單的所有數據
- 2022-09-19 LyScript尋找ROP漏洞指令片段的方法詳解_python
- 2022-04-21 Python的索引與切片原來該這樣理解_python
- 2022-09-19 ASP.NET?Core模仿中間件方式實現列表過濾功能_實用技巧
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支