React工作流程及Error Boundaries實現(xiàn)過程講解
這里簡單講解下React工作流程,后文有用。分為三步:
觸發(fā)更新
- render階段:計算更新會造成的副作用
- commit階段:在宿主環(huán)境執(zhí)行副作用
副作用有很多,比如:
- 插入DOM節(jié)點
- 執(zhí)行useEffect回調(diào)
好了,讓我們進入主題。
什么是Error Boundaries
React提供了兩個與錯誤處理相關的API:
- getDerivedStateFromError:靜態(tài)方法,當錯誤發(fā)生后提供一個機會渲染fallback
- UIcomponentDidCatch:組件實例方法,當錯誤發(fā)生后提供一個機會記錄錯誤信息
使用了這兩個API的ClassComponent通常被稱為Error Boundaries(錯誤邊界)。
在Error Boundaries的子孫組件中發(fā)生的所有React工作流程內(nèi)的錯誤都會被Error Boundaries捕獲。
通過開篇的介紹可以知道,React工作流程指:
render階段
commit階段
考慮如下代碼:
class ErrorBoundary extends Component {
componentDidCatch(e) {
console.warn(“發(fā)生錯誤”, e);
}
render() {
return <div>{this.props.children}</div>;
}
}
const App = () => (
<ErrorBoundary>
<A><B/></A>
<C/>
<ErrorBoundary>
)A、B、C作為ErrorBoundary的子孫組件,當發(fā)生React工作流程內(nèi)的錯誤,都會被ErrorBoundary中的componentDidCatch方法捕獲。
步驟1:捕獲錯誤
首先來看工作流程中的錯誤都是何時被捕獲的。
render階段的核心代碼如下,發(fā)生的錯誤會被handleError處理:
do {
try {
// 對于并發(fā)更新則是workLoopConcurrent
workLoopSync();
break;
} catch (thrownValue) {
handleError(root, thrownValue);
}
} while (true);commit階段包含很多工作,比如:
- componentDidMount/Update執(zhí)行
- 綁定/解綁ref
- useEffect/useLayoutEffect callback與destroy執(zhí)行
這些工作會以如下形式執(zhí)行,發(fā)生的錯誤被captureCommitPhaseError處理:
try {
// …執(zhí)行某項工作
} catch (error) {
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
// ...為了可讀性,邏輯有刪減
function createClassErrorUpdate() {
if (typeof getDerivedStateFromError === 'function') {
// 用于執(zhí)行getDerivedStateFromError的callback
update.payload = () => {
return getDerivedStateFromError(error);
};
// 用于拋出React提示信息的callback
update.callback = () => {
logCapturedError(fiber, errorInfo);
};
}
if (inst !== null && typeof inst.componentDidCatch === 'function') {
// 用于執(zhí)行componentDidCatch的callback
update.callback = function callback() {
this.componentDidCatch(error);
};
}
return update;
}如果沒有找到Error Boundaries,繼續(xù)向上遍歷直到根節(jié)點。
此時會構造:
用于拋出未捕獲錯誤的callback用于拋出React提示信息的callback
// ...為了可讀性,邏輯有刪減
funffction createRootErrorUpdate() {
// 用于拋出“未捕獲的錯誤”及“React的提示信息”的callback
update.callback = () => {
onUncaughtError(error);
logCapturedError(fiber, errorInfo);
};
return update;
}執(zhí)行callback
構造好的callback在什么時候執(zhí)行呢?
在React中有兩個執(zhí)行用戶自定義callback的API:
對于ClassComponent, this.setState(newState, callback)中newState和callback參數(shù)都能傳遞Function作為callback
所以,對于Error Boundaries,相當于主動觸發(fā)了一次更新:
this.setState(() => {
// 用于執(zhí)行getDerivedStateFromError的callback
}, () => {
// 用于執(zhí)行componentDidCatch的callback
// 以及 用于拋出React提示信息的callback
})對于根節(jié)點,執(zhí)行ReactDOM.render(element, container, callback)中callback參數(shù)能傳遞Function作為callback
所以,對于沒有Error Boundaries的情況,相當于主動執(zhí)行了如下函數(shù):
ReactDOM.render(element, container, () => {
// 用于拋出“未捕獲的錯誤”及“React的提示信息”的callback
})所以,Error Boundaries的實現(xiàn)可以看作是:React利用已有API實現(xiàn)的新功能。
總結
經(jīng)常有人問:為什么Hooks沒有Error Boundaries?
可以看到,Error Boundaries的實現(xiàn)借助了this.setState可以傳遞callback的特性,useState暫時無法完全對標。
以上就是React工作流程及Error Boundaries實現(xiàn)過程講解的詳細內(nèi)容,更多關于React工作流程Error Boundaries實現(xiàn)過程的資料請關注腳本之家其它相關文章!
相關文章
react-native使用react-navigation進行頁面跳轉導航的示例
本篇文章主要介紹了react-native使用react-navigation進行頁面跳轉導航的示例,具有一定的參考價值,有興趣的可以了解一下2017-09-09
react?+?vite?+?ts項目中優(yōu)雅使用.svg文件
這篇文章主要為大家介紹了react?+?vite?+?ts項目中優(yōu)雅使用.svg文件,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-08-08
react循環(huán)數(shù)據(jù)(列表)的實現(xiàn)
這篇文章主要介紹了react循環(huán)數(shù)據(jù)的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-04-04

