成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Error Boundaries是這么實現的,還挺巧妙

開發 前端
本文會講解React中Error Boundaries的完整實現邏輯。Error Boundaries的實現借助了this.setState可以傳遞callback的特性,useState暫時無法完全對標。

[[438303]]

大家好,我卡頌。

本文會講解React中Error Boundaries的完整實現邏輯。

一張圖概括:

這里簡單講解下React工作流程,后文有用。分為三步:

  1. 觸發更新
  2. render階段:計算更新會造成的副作用
  3. commit階段:在宿主環境執行副作用

副作用有很多,比如:

  • 插入DOM節點
  • 執行useEffect回調

好了,讓我們進入主題。

什么是Error BoundariesReact

提供了兩個與「錯誤處理」相關的API:

  • getDerivedStateFromError:靜態方法,當錯誤發生后提供一個機會渲染fallback UI
  • componentDidCatch:組件實例方法,當錯誤發生后提供一個機會記錄錯誤信息

使用了這兩個API的ClassComponent通常被稱為Error Boundaries(錯誤邊界)。

在Error Boundaries的「子孫組件」中發生的所有「React工作流程內」的錯誤都會被Error Boundaries捕獲。

通過開篇的介紹可以知道,「React工作流程」指:

  • render階段
  • commit階段

考慮如下代碼:

  1. class ErrorBoundary extends Component { 
  2.   componentDidCatch(e) { 
  3.     console.warn(“發生錯誤”, e); 
  4.   } 
  5.   render() { 
  6.     return <div>{this.props.children}</div>; 
  7.   } 
  8.  
  9. const App = () => ( 
  10.  <ErrorBoundary> 
  11.     <A><B/></A> 
  12.     <C/> 
  13.  <ErrorBoundary> 

 A、B、C作為ErrorBoundary的子孫組件,當發生「React工作流程內」的錯誤,都會被ErrorBoundary中的componentDidCatch方法捕獲。

步驟1:捕獲錯誤

首先來看「工作流程中的錯誤都是何時被捕獲的」。

render階段的核心代碼如下,發生的錯誤會被handleError處理:

  1. do { 
  2.   try { 
  3.     // 對于并發更新則是workLoopConcurrent 
  4. workLoopSync(); 
  5.     break; 
  6.   } catch (thrownValue) { 
  7.     handleError(root, thrownValue); 
  8.   } 
  9. } while (true); 

commit階段包含很多工作,比如:

  • componentDidMount/Update執行
  • 綁定/解綁ref
  • useEffect/useLayoutEffect callback與destroy執行

這些工作會以如下形式執行,發生的錯誤被captureCommitPhaseError處理:

  1. try { 
  2. // …執行某項工作  
  3. } catch (error) { 
  4.   captureCommitPhaseError(fiber, fiber.return, error); 

步驟2:構造callback

可以發現,即使沒有Error Boundaries,「工作流程」中的錯誤已經被React捕獲了。而正確的邏輯應該是:

  • 如果存在Error Boundaries,執行對應API
  • 拋出React的提示信息
  • 如果不存在Error Boundaries,拋出「未捕獲的錯誤」

所以,不管是handleError還是captureCommitPhaseError,都會從發生錯誤的節點的父節點開始,逐層向上遍歷,尋找最近的Error Boundaries。

一旦找到,就會構造:

  • 用于「執行Error Boundaries API」的callback
  • 用于「拋出React提示信息」的callback

React錯誤提示信息,包括提示語和錯誤堆棧

  1.   // ...為了可讀性,邏輯有刪減 
  2. function createClassErrorUpdate() { 
  3.   if (typeof getDerivedStateFromError === 'function') { 
  4. // 用于執行getDerivedStateFromError的callback 
  5.     update.payload = () => { 
  6.       return getDerivedStateFromError(error); 
  7. }; 
  8. // 用于拋出React提示信息的callback 
  9.     update.callback = () => { 
  10.       logCapturedError(fiber, errorInfo); 
  11.     }; 
  12.   } 
  13.   if (inst !== null && typeof inst.componentDidCatch === 'function') { 
  14. // 用于執行componentDidCatch的callback 
  15.     update.callback = function callback() { 
  16.       this.componentDidCatch(error); 
  17.     }; 
  18.   } 
  19.   return update

如果沒有找到Error Boundaries,繼續向上遍歷直到根節點。

此時會構造:

  • 用于「拋出未捕獲錯誤」的callback
  • 用于「拋出React提示信息」的callback
  1. // ...為了可讀性,邏輯有刪減 
  2. funffction createRootErrorUpdate() { 
  3.   // 用于拋出“未捕獲的錯誤”及“React的提示信息”的callback 
  4.   update.callback = () => { 
  5.     onUncaughtError(error); 
  6.     logCapturedError(fiber, errorInfo); 
  7.   }; 
  8.   return update

執行callback

構造好的callback在什么時候執行呢?

在React中有兩個「執行用戶自定義callback」的API:

  • 對于ClassComponent, this.setState(newState, callback)中newState和callback參數都能傳遞Function作為callback

所以,對于Error Boundaries,相當于主動觸發了一次更新:

  1. this.setState(() => { 
  2.   // 用于執行getDerivedStateFromError的callback 
  3. }, () => { 
  4.   // 用于執行componentDidCatch的callback 
  5.   //  以及 用于拋出React提示信息的callback 
  6. }) 
  • 對于根節點,執行ReactDOM.render(element, container, callback)中callback參數能傳遞Function作為callback

所以,對于「沒有Error Boundaries」的情況,相當于主動執行了如下函數:

  1. ReactDOM.render(element, container, () => { 
  2. // 用于拋出“未捕獲的錯誤”及“React的提示信息”的callback 
  3. }) 

所以,Error Boundaries的實現可以看作是:React利用已有API實現的新功能。

總結

經常有人問:為什么Hooks沒有Error Boundaries?

可以看到,Error Boundaries的實現借助了this.setState可以傳遞callback的特性,useState暫時無法完全對標。

最后,給你留個作業,在官方文檔[1]介紹了4種情況的錯誤不會被Error Boundaries捕獲。

利用本文知識,你能分析下他們為什么不會被捕獲么?

參考資料

[1]官方文檔:

https://reactjs.org/docs/error-boundaries.html#introducing-error-boundaries

 

責任編輯:姜華 來源: 魔術師卡頌
相關推薦

2019-06-17 14:20:51

Redis數據庫Java

2019-05-27 09:14:28

2021-10-31 23:57:33

Eslint原理

2024-01-03 08:48:09

NilAway靜態分析工具

2022-09-05 08:39:55

Redis存儲數據

2023-03-26 00:04:14

2019-02-28 10:40:13

Windows 功能系統

2022-01-07 07:59:14

Go語言Go Error

2022-01-14 17:01:44

GoError結構

2010-01-22 16:10:12

C++ Builder

2025-05-12 08:43:08

IO性能映射

2009-09-14 10:45:33

LINQ刪除數據

2010-08-31 13:56:38

PHP5多線程

2021-12-03 06:02:19

CSS濾鏡前端

2021-12-15 06:18:23

iOS15.2蘋果 iOS

2019-07-16 13:50:49

Windows 功能系統

2021-01-26 09:14:19

Linux內核模塊

2017-02-24 13:20:13

搜索引擎數據結構架構

2009-11-18 15:39:43

PHP函數

2011-02-24 13:34:09

資源共享
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产真实精品久久二三区 | 欧美一区二区网站 | 亚洲精品久久久蜜桃 | 午夜视频在线免费观看 | 国产中文 | 亚洲精品日韩精品 | 成人日韩| 成人国产在线视频 | 91在线电影 | 99亚洲国产精品 | 色综久久 | 日韩欧美一区二区三区在线播放 | 狠狠av | 久久久久久久成人 | 欧美成人a∨高清免费观看 老司机午夜性大片 | 欧美日韩一区二区三区在线观看 | 国产女人与拘做受免费视频 | 国产成人免费视频网站高清观看视频 | 久久精品com | 国产精品免费一区二区三区四区 | 国产精品久久久久久久久久久久久久 | 欧美专区在线视频 | 男女性毛片 | 中文字幕 国产 | 亚洲精品白浆高清久久久久久 | 亚洲精品国产a久久久久久 午夜影院网站 | 国产一区二区三区久久久久久久久 | 亚洲一区二区 | www.亚洲成人网 | 免费在线观看av的网站 | 天堂精品视频 | 国产高清视频在线观看 | 一级二级三级在线观看 | 日韩免费看片 | 日韩精品在线免费观看视频 | 久久人人爽人人爽 | 一区二区三区视频在线 | 久热爱 | 亚洲午夜网| 福利视频二区 | 日韩在线一区二区三区 |