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

Error Boundaries是這么實現(xiàn)的,還挺巧妙

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

[[438303]]

大家好,我卡頌。

本文會講解React中Error Boundaries的完整實現(xiàn)邏輯。

一張圖概括:

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

  1. 觸發(fā)更新
  2. render階段:計算更新會造成的副作用
  3. commit階段:在宿主環(huán)境執(zhí)行副作用

副作用有很多,比如:

  • 插入DOM節(jié)點
  • 執(zhí)行useEffect回調(diào)

好了,讓我們進入主題。

什么是Error BoundariesReact

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

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

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

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

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

  • render階段
  • commit階段

考慮如下代碼:

  1. class ErrorBoundary extends Component { 
  2.   componentDidCatch(e) { 
  3.     console.warn(“發(fā)生錯誤”, 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的子孫組件,當發(fā)生「React工作流程內(nèi)」的錯誤,都會被ErrorBoundary中的componentDidCatch方法捕獲。

步驟1:捕獲錯誤

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

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

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

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

  • componentDidMount/Update執(zhí)行
  • 綁定/解綁ref
  • useEffect/useLayoutEffect callback與destroy執(zhí)行

這些工作會以如下形式執(zhí)行,發(fā)生的錯誤被captureCommitPhaseError處理:

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

步驟2:構造callback

可以發(fā)現(xiàn),即使沒有Error Boundaries,「工作流程」中的錯誤已經(jīng)被React捕獲了。而正確的邏輯應該是:

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

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

一旦找到,就會構造:

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

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

  1.   // ...為了可讀性,邏輯有刪減 
  2. function createClassErrorUpdate() { 
  3.   if (typeof getDerivedStateFromError === 'function') { 
  4. // 用于執(zhí)行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. // 用于執(zhí)行componentDidCatch的callback 
  15.     update.callback = function callback() { 
  16.       this.componentDidCatch(error); 
  17.     }; 
  18.   } 
  19.   return update

如果沒有找到Error Boundaries,繼續(xù)向上遍歷直到根節(jié)點。

此時會構造:

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

執(zhí)行callback

構造好的callback在什么時候執(zhí)行呢?

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

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

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

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

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

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

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

總結

經(jīng)常有人問:為什么Hooks沒有Error Boundaries?

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

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

利用本文知識,你能分析下他們?yōu)槭裁床粫徊东@么?

參考資料

[1]官方文檔:

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

 

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

2019-06-17 14:20:51

Redis數(shù)據(jù)庫Java

2019-05-27 09:14:28

2024-01-03 08:48:09

NilAway靜態(tài)分析工具

2021-10-31 23:57:33

Eslint原理

2022-09-05 08:39:55

Redis存儲數(shù)據(jù)

2023-03-26 00:04:14

2019-02-28 10:40:13

Windows 功能系統(tǒng)

2022-01-07 07:59:14

Go語言Go Error

2022-01-14 17:01:44

GoError結構

2025-05-12 08:43:08

IO性能映射

2009-09-14 10:45:33

LINQ刪除數(shù)據(jù)

2010-01-22 16:10:12

C++ Builder

2021-12-15 06:18:23

iOS15.2蘋果 iOS

2021-12-03 06:02:19

CSS濾鏡前端

2010-08-31 13:56:38

PHP5多線程

2019-07-16 13:50:49

Windows 功能系統(tǒng)

2021-01-26 09:14:19

Linux內(nèi)核模塊

2009-11-18 15:39:43

PHP函數(shù)

2011-02-24 13:34:09

資源共享

2017-02-24 13:20:13

搜索引擎數(shù)據(jù)結構架構
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 紧缚调教一区二区三区视频 | 日本不卡免费新一二三区 | 午夜午夜精品一区二区三区文 | 欧美日韩三级视频 | 成人av免费 | 91视频电影 | 色毛片| 国产一级片91| 久久久久久av | 国产一在线观看 | 黄色一级特级片 | 精品一二 | 久久爱一区 | 一区二区三区视频在线观看 | 日韩av一区二区在线观看 | 国产精品成人国产乱一区 | 日韩在线| 欧美一区视频 | 日本又色又爽又黄又高潮 | 国内毛片毛片毛片毛片 | 久久久久久久久久久久91 | 国产精品国产 | 欧美一级全黄 | 精品国产乱码久久久久久久久 | 亚洲精品自拍视频 | 日本一本视频 | 久久国产精品视频 | 亚洲小视频在线观看 | 精品一区二区三区四区视频 | 黄色网址在线播放 | 日日草夜夜草 | 亚洲精品久久久久中文字幕欢迎你 | 久热国产精品视频 | 日韩一区二区免费视频 | 一级毛片视频 | 国产精产国品一二三产区视频 | 黄色一级大片在线免费看产 | 精品毛片视频 | 久久毛片 | 国产精品久久久久无码av | 色综合久 |