網站首頁 編程語言 正文
這里簡單講解下React工作流程,后文有用。分為三步:
觸發更新
- render階段:計算更新會造成的副作用
- commit階段:在宿主環境執行副作用
副作用有很多,比如:
- 插入DOM節點
- 執行useEffect回調
好了,讓我們進入主題。
什么是Error Boundaries
React提供了兩個與錯誤處理相關的API:
- getDerivedStateFromError:靜態方法,當錯誤發生后提供一個機會渲染fallback
- UIcomponentDidCatch:組件實例方法,當錯誤發生后提供一個機會記錄錯誤信息
使用了這兩個API的ClassComponent通常被稱為Error Boundaries(錯誤邊界)。
在Error Boundaries的子孫組件中發生的所有React工作流程內的錯誤都會被Error Boundaries捕獲。
通過開篇的介紹可以知道,React工作流程指:
render階段
commit階段
考慮如下代碼:
class ErrorBoundary extends Component { componentDidCatch(e) { console.warn(“發生錯誤”, e); } render() { return <div>{this.props.children}</div>; } } const App = () => ( <ErrorBoundary> <A><B/></A> <C/> <ErrorBoundary> )
A、B、C作為ErrorBoundary的子孫組件,當發生React工作流程內的錯誤,都會被ErrorBoundary中的componentDidCatch方法捕獲。
步驟1:捕獲錯誤
首先來看工作流程中的錯誤都是何時被捕獲的。
render階段的核心代碼如下,發生的錯誤會被handleError處理:
do { try { // 對于并發更新則是workLoopConcurrent workLoopSync(); break; } catch (thrownValue) { handleError(root, thrownValue); } } while (true);
commit階段包含很多工作,比如:
- componentDidMount/Update執行
- 綁定/解綁ref
- useEffect/useLayoutEffect?callback與destroy執行
這些工作會以如下形式執行,發生的錯誤被captureCommitPhaseError處理:
try { // …執行某項工作 } catch (error) { 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
// ...為了可讀性,邏輯有刪減 function createClassErrorUpdate() { if (typeof getDerivedStateFromError === 'function') { // 用于執行getDerivedStateFromError的callback update.payload = () => { return getDerivedStateFromError(error); }; // 用于拋出React提示信息的callback update.callback = () => { logCapturedError(fiber, errorInfo); }; } if (inst !== null && typeof inst.componentDidCatch === 'function') { // 用于執行componentDidCatch的callback update.callback = function callback() { this.componentDidCatch(error); }; } return update; }
如果沒有找到Error Boundaries,繼續向上遍歷直到根節點。
此時會構造:
用于拋出未捕獲錯誤的callback用于拋出React提示信息的callback
// ...為了可讀性,邏輯有刪減 funffction createRootErrorUpdate() { // 用于拋出“未捕獲的錯誤”及“React的提示信息”的callback update.callback = () => { onUncaughtError(error); logCapturedError(fiber, errorInfo); }; return update; }
執行callback
構造好的callback在什么時候執行呢?
在React中有兩個執行用戶自定義callback的API:
對于ClassComponent,?this.setState(newState, callback)中newState和callback參數都能傳遞Function作為callback
所以,對于Error Boundaries,相當于主動觸發了一次更新:
this.setState(() => { // 用于執行getDerivedStateFromError的callback }, () => { // 用于執行componentDidCatch的callback // 以及 用于拋出React提示信息的callback })
對于根節點,執行ReactDOM.render(element, container, callback)中callback參數能傳遞Function作為callback
所以,對于沒有Error Boundaries的情況,相當于主動執行了如下函數:
ReactDOM.render(element, container, () => { // 用于拋出“未捕獲的錯誤”及“React的提示信息”的callback })
所以,Error Boundaries的實現可以看作是:React利用已有API實現的新功能。
總結
經常有人問:為什么Hooks沒有Error Boundaries?
可以看到,Error Boundaries的實現借助了this.setState可以傳遞callback的特性,useState暫時無法完全對標。
原文鏈接:https://blog.csdn.net/weixin_41996102/article/details/121701694
相關推薦
- 2022-07-22 C語言輸出所有水仙花數
- 2022-08-01 MongoDB基礎之查詢文檔_MongoDB
- 2022-11-15 簡單實現Android應用的啟動頁_Android
- 2023-07-18 IDEA中springboot的熱加載thymeleaf靜態html頁面
- 2022-12-06 R語言如何畫豎線、橫線、添加標簽以及畫固定長度的線段_R語言
- 2022-04-22 如何讓electron收到消息發出聲音
- 2022-05-06 SQLite3+Qt開發:SQLite3簡要介紹+在Qt5中使用步驟
- 2022-02-28 react高階函數和函數柯里化 學習
- 最近更新
-
- 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同步修改后的遠程分支