網(wǎng)站首頁 編程語言 正文
引言
過去,組件內(nèi)的代碼異常會(huì)導(dǎo)致 React 的內(nèi)部狀態(tài)被破壞,產(chǎn)生可能無法追蹤的錯(cuò)誤。但 React 并沒有提供一種優(yōu)雅處理這些錯(cuò)誤的方式,也無法從錯(cuò)誤中恢復(fù)。
默認(rèn)情況下,若一個(gè)組件在渲染期間(render)發(fā)生錯(cuò)誤,會(huì)導(dǎo)致整個(gè)組件樹全部被卸載,這當(dāng)然不是我們期望的結(jié)果。
部分組件的錯(cuò)誤不應(yīng)該導(dǎo)致整個(gè)應(yīng)用崩潰。為了解決這個(gè)問題,React 16 引入了一個(gè)新的概念 —— 錯(cuò)誤邊界
錯(cuò)誤邊界是一種 React 組件,這種組件可以捕獲發(fā)生在其子組件樹任何位置的異常,并打印這些錯(cuò)誤,同時(shí)展示降級(jí) UI,而并不會(huì)渲染那些發(fā)生崩潰的子組件樹。
注意
- 錯(cuò)誤邊界目前只在
Class Component
中實(shí)現(xiàn)了,沒有在hooks
中實(shí)現(xiàn)(因?yàn)镋rror Boundaries的實(shí)現(xiàn)借助了this.setState可以傳遞callback的特性,useState無法傳入回調(diào),所以無法完全對(duì)標(biāo)); - 錯(cuò)誤邊界 無法捕獲 以下四種場(chǎng)景中產(chǎn)生的錯(cuò)誤:
- 事件處理函數(shù)(因?yàn)?Error Boundaries 實(shí)現(xiàn)的本質(zhì)是觸發(fā)更新,但是事件處理函數(shù)不在render或者commit階段,所以無法進(jìn)行捕獲,如果你需要在事件處理器內(nèi)部捕獲錯(cuò)誤,可以使用原生的
try
?/?catch
?語句 了解更多) - 異步代碼(例如?
setTimeout
?或?requestAnimationFrame
?回調(diào)函數(shù)) - 服務(wù)端渲染(因?yàn)橛|發(fā)更新只能在客戶端進(jìn)行,不能在serve端進(jìn)行)
- 它自身拋出來的錯(cuò)誤(因?yàn)殄e(cuò)誤拋出要向父節(jié)點(diǎn)冒泡尋找 Error Boundaries 處理,無法處理自身產(chǎn)生的錯(cuò)誤)
- 事件處理函數(shù)(因?yàn)?Error Boundaries 實(shí)現(xiàn)的本質(zhì)是觸發(fā)更新,但是事件處理函數(shù)不在render或者commit階段,所以無法進(jìn)行捕獲,如果你需要在事件處理器內(nèi)部捕獲錯(cuò)誤,可以使用原生的
實(shí)現(xiàn)
React中提供了兩個(gè)與錯(cuò)誤處理相關(guān)的api:
-
getderivedstatefromerror
:靜態(tài)方法,當(dāng)錯(cuò)誤發(fā)生后,提供一個(gè)機(jī)會(huì)渲染 Fallback UI -
componentDidCatch
:組件實(shí)例方法,當(dāng)錯(cuò)誤發(fā)生后,提供一個(gè)機(jī)會(huì)記錄錯(cuò)誤信息
如果一個(gè) class 組件中定義了?getDerivedStateFromError()?或?componentDidCatch()?這兩個(gè)生命周期方法中的任意一個(gè)(或兩個(gè))時(shí),那么它就變成一個(gè)錯(cuò)誤邊界。當(dāng)拋出錯(cuò)誤后,請(qǐng)使用?getDerivedStateFromError()
?渲染備用 UI ,使用?componentDidCatch()
?打印錯(cuò)誤信息。
class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false, }; } getDerivedStateFromError(error) { // 更新 state 使下一次渲染能夠顯示降級(jí)后的 UI return { hasError: true }; } componentDidCatch(error, errorInfo) { // 你同樣可以將錯(cuò)誤日志上報(bào)給服務(wù)器 logErrorToService(error, errorInfo); } render() { if (this.state.hasError) { // 你可以自定義降級(jí)后的 UI 并渲染 return <h1>wrong message</h1>; } return this.props.children; } } export default ErrorBoundary;
然后你可以將它作為一個(gè)常規(guī)組件去使用:
<ErrorBoundary> <A /> <B /> <C /> </ErrorBoundary>
錯(cuò)誤邊界的工作方式類似于原生的?catch {}
,不同的地方在于,錯(cuò)誤邊界只針對(duì) React 組件。并且只有 class 組件才可以成為錯(cuò)誤邊界組件。大多數(shù)情況下, 你只需要聲明一次錯(cuò)誤邊界組件, 并在整個(gè)應(yīng)用中使用它。
錯(cuò)誤邊界應(yīng)該放置在哪?
錯(cuò)誤邊界的粒度由你來決定,可以將其包裝在最頂層的路由組件中,并為用戶展示一個(gè) “xxx” 的錯(cuò)誤信息,就像服務(wù)端框架經(jīng)常處理崩潰一樣。也可以將單獨(dú)的組件包裝在錯(cuò)誤邊界,從而保護(hù)其它組件不會(huì)崩潰。(例如,F(xiàn)acebook Messenger 將側(cè)邊欄、信息面板、聊天記錄以及信息輸入框包裝在單獨(dú)的錯(cuò)誤邊界中。如果其中的某些 UI 組件崩潰,其余部分仍然能夠交互。)
未捕獲錯(cuò)誤(Uncaught Errors)該如何處理?
自 React 16 起,任何未被錯(cuò)誤邊界捕獲的錯(cuò)誤將會(huì)導(dǎo)致整個(gè) React 組件樹被卸載。
在某些場(chǎng)景下,把一個(gè)錯(cuò)誤的 UI 留在那,比完全移除它要更糟糕。比如在類似 Messenger 的產(chǎn)品中,把一個(gè)異常的 UI 展示給用戶,可能會(huì)導(dǎo)致用戶把錯(cuò)誤信息發(fā)給別人。同樣,對(duì)于支付類場(chǎng)景而言,與其顯示錯(cuò)誤的支付金額,不如直接讓頁面白屏。
(所以,錯(cuò)誤邊界的使用難點(diǎn)在于尋找合適的時(shí)機(jī)
,知道在什么時(shí)候該用
,什么時(shí)候不該用
,這是一個(gè)充滿哲學(xué)的問題)
注意:自 React 15 的命名更改
React 15 中有一個(gè)支持有限的錯(cuò)誤邊界方法?unstable_handleError
。這個(gè)方法不再起作用,自 React 16 起你需要在代碼中將其修改為?componentDidCatch
。
原文鏈接:https://juejin.cn/post/7040689855205998605
相關(guān)推薦
- 2023-03-26 數(shù)據(jù)結(jié)構(gòu)TypeScript之棧和隊(duì)列詳解_其它
- 2022-03-11 部署.Net6項(xiàng)目到docker_基礎(chǔ)應(yīng)用
- 2023-03-20 Redis使用Bitmap的方法實(shí)現(xiàn)_Redis
- 2022-08-22 C#使用MSTest進(jìn)行單元測(cè)試_C#教程
- 2022-10-02 Blender?Python編程創(chuàng)建發(fā)光材質(zhì)示例詳解_python
- 2022-06-26 Android開發(fā)快速實(shí)現(xiàn)底部導(dǎo)航欄示例_Android
- 2022-02-01 通過url路徑下載服務(wù)器文件
- 2023-07-09 el-table操作列的按鈕超過三個(gè)時(shí),動(dòng)態(tài)計(jì)算,將多余的按鈕放入更多el-dropdown-men
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支