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

為什么Hook沒有ErrorBoundary?

開發 前端
ErrorBoundary?在ClassComponent?中的實現使用了this.setState?的回調函數特性,這使得Hooks中要完全實現同樣功能,需要額外開發成本。

大家好,我卡頌。

在很多全面使用Hooks開發的團隊,唯一使用ClassComponent的場景就是「使用ClassComponent創建ErrorBoundary」。

可以說,如果Hooks存在如下兩個生命周期函數的替代品,就能全面拋棄ClassComponent了:

  • getDerivedStateFromError
  • componentDidCatch

那為什么還沒有對標的Hook呢?

今天我們從上述兩個生命周期函數的實現原理,以及要移植到Hook上需要付出的成本來談論這個問題。

ErrorBoundary實現原理

ErrorBoundary可以捕獲子孫組件中「React工作流程」內的錯誤。

「React工作流程」指:

  • render階段,即「組件render」、「Diff算法」發生的階段。
  • commit階段,即「渲染DOM」、「componentDidMount/Update執行」的階段。

這也是為什么「事件回調中發生的錯誤」無法被ErrorBoundary捕獲 —— 事件回調并不屬于「React工作流程」。

如何捕獲錯誤

「render階段」的整體執行流程如下:

do {
try {
// render階段具體的執行流程
workLoop();
break;
} catch (thrownValue) {
handleError(root, thrownValue);
}
} while (true);

可以發現,如果「render階段」發生錯誤,會被捕獲并執行handleError方法。

類似的,「commit階段」的整體執行流程如下:

try {
// ...具體執行流程
} catch (error) {
captureCommitPhaseError(current, nearestMountedAncestor, error);
}

如果「commit階段」發生錯誤,會被捕獲并執行captureCommitPhaseError方法。getDerivedStateFromError原理。

捕獲后的錯誤如何處理呢?

我們知道,ClassComponent中this.setState第一個參數,除了可以接收「新的狀態」,也能接收「改變狀態的函數」作為參數:

// 可以這樣
this.setState(this.state.num + 1)
// 也可以這樣
this.setState(num => num + 1)

getDerivedStateFromError的實現,就借助了this.setState中「改變狀態的函數」這一特性。

當捕獲錯誤后,即:

  • 對于「render階段」,handleError執行后。
  • 對于「commit階段」,captureCommitPhaseError執行后。

會在ErrorBoundary對應組件中觸發類似如下更新:

this.setState(
getDerivedStateFromError.bind(null, error)
)

這就是為什么getDerivedStateFromError要求開發者返回「新的state」— 本質來說,他就是觸發一次新的更新。

componentDidCatch原理

再來看另一個ErrorBoundary相關的生命周期函數— componentDidCatch。

ClassComponent中this.setState的第二個參數,可以接收「回調函數」作為參數:

this.setState(newState, () => {
// ...回調
})

當觸發的更新渲染到頁面后,回調會觸發。

這就是componentDidCatch的實現原理。

當捕獲錯誤后,會在ErrorBoundary對應組件中觸發類似如下更新:

this.setState(this.state, componentDidCatch.bind(this, error))

處理“未捕獲”的錯誤

可以發現,「React運行流程」中的錯誤,都已經被React自身捕獲了,再交由ErrorBoundary處理。

如果沒有定義ErrorBoundary,這些「被捕獲的錯誤」需要重新拋出,營造「錯誤未被捕獲的感覺」。

那這一步在哪里執行呢?

與this.setState類似,ReactDOM.render(element, container[, callback])第三個參數也能接收「回調函數」。

如果開發者沒有定義ErrorBoundary,那么React最終會在ReactDOM.render的回調中拋出錯誤。

可以發現,在ClassComponent中ErrorBoundary的實現完全依賴了ClassComponent已有的特性。

而Hooks本身并不存在類似this.setState的回調特性,所以實現起來會比較復雜。

實現Hooks中的ErrorBoundary

除了上述談到的阻礙,FunctionComponent與ClassComponent在源碼層面的運行流程也有細節上的差異,要照搬實現也有一定難度。

如果一定要實現,在「最大程度復用現有基礎設施」的指導方針下,useErrorBoundary(ErrorBoundary在Hooks中的實現)的使用方式應該類似如下:

function ErrorBoundary({children}: {children: ReactNode}) {
const [errorMsg, updateError] = useState<Error | null>(null);
useErrorBoundary((e: Error) => {
// 捕獲到錯誤,觸發更新
updateError(e);
})
return (
<div>
{errorMsg ? '報錯:' + errorMsg.toString() : children}
</div>
)
}

其中useErrorBoundary的觸發方式類似useEffect:

useErrorBoundary((e: Error) => {
// ...
})
// 類似
useEffect(() => {
// ...
})

筆者仿照ClassComponent中ErrorBoundary的實現原理與useEffect的實現原理,實現了原生Hooks — useErrorBoundary。

感興趣的朋友可以在useErrorBoundary在線示例[1]體驗效果。

總結

ErrorBoundary在ClassComponent中的實現使用了this.setState的回調函數特性,這使得Hooks中要完全實現同樣功能,需要額外開發成本。

筆者猜測,這是沒有提供對應原生Hooks的原因之一。

參考資料

[1]useErrorBoundary在線示例:https://codesandbox.io/s/angry-mountain-xstgj4?file=/src/App.js。

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

2020-07-22 07:55:12

Python開發函數

2022-05-22 21:23:10

前端監控系統

2013-03-18 09:30:18

Lisp

2015-11-30 19:01:38

樂視生態

2018-03-21 10:00:14

混合云爆發發生

2020-08-23 11:03:24

Python開發void

2020-06-01 21:24:50

物聯網應用程序IOT

2022-07-13 15:23:57

Vue fiberreact前端

2016-10-24 14:35:04

2012-08-07 16:46:35

蘋果Apple TV

2024-04-10 09:05:37

2021-07-21 09:35:36

switchbreakJava

2017-07-03 10:52:20

深度學習人工智能

2025-03-21 10:33:22

2024-01-03 07:50:09

云計算數據中心ITSM

2021-02-01 10:10:55

Svelte框架開發

2023-08-28 09:05:46

LinuxJVM開源

2009-06-15 08:37:08

微軟Windows 7操作系統

2011-12-21 09:14:44

虛擬化桌面虛擬化訪問虛擬化

2021-08-30 09:57:40

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚州影院| 国产一级视频在线观看 | 91网站在线播放 | 国产免费一区二区三区 | 亚洲国产中文字幕 | 国产欧美在线观看 | 99久久中文字幕三级久久日本 | 中文字幕第90页 | 免费一二区 | 国产精品免费观看 | 国产精品久久久久久久久久久久午夜片 | 天天操 天天操 | 国产97碰免费视频 | 伊人网一区| 欧美www在线观看 | 一区二区在线观看av | 亚洲欧洲日本国产 | 成人在线精品视频 | 久久精品一区二区三区四区 | 亚洲欧美精品一区 | 久久久久成人精品 | 亚洲一区二区三区视频 | 久国产 | 国产精品美女久久久久 | 亚洲第一视频 | 亚洲日日夜夜 | 蜜桃一区二区三区在线 | 久久精品伊人 | 中文字幕精品一区久久久久 | 黄色av网站在线观看 | 成人精品免费视频 | 天天操人人干 | 婷婷久久综合 | 成人午夜精品 | 日批日韩在线观看 | 特黄色一级毛片 | 99成人| 国产精品久久久久久久久久久免费看 | 欧美成人一区二区三区 | 国产乱码久久久 | 国产高清在线精品 |