網站首頁 編程語言 正文
該文章翻譯自官網 https://reactjs.org/docs/error-boundaries.html 該文章包含以下內容:
1.Error Boundaries介紹
2.ComponentDidCatch 函數的參數
3.觸發error boundaries后程序要走向哪里?
4.對于不能捕獲的錯誤的新處理方式
5.在堆中跟蹤component
6.try/catch 如何?
7.Event Handlers怎么樣?
8.React 15后的函數命名改變
在過去,React組件中的js錯誤通常會污染React的內部state并且造成它發出一個讓人難以理解的錯誤給下一個Render,我們在控制臺看到的異常往往是由更內層的程序代碼引起的,但是React并沒有提供一個方式讓我們在組件中優雅的解決他們并恢復業務邏輯。
Error Boundaries介紹
UI的某部分引起的JS錯誤不應該破壞整個程序,為了幫React的使用者解決這個問題,React 16介紹了一種關于錯誤邊界(error boundary)的新觀念。
error boundaries 讓react組件可以捕獲在他們子級組件樹任何地方的錯誤,并且打印出這些錯誤和演示一個預備UI(fallback UI),從而替換那些出現異常的組件樹。Error boundaries在rendering,lifeCyclemethod或處于他們樹層級之下的構造函數中捕獲錯誤。
(注釋:lifecycle method是react固有名詞,包括componentWillUpdate,componentWillReceiveProps,render等方法,這些方法會自動調用)
注意: error boundaries并不會捕捉這些錯誤:
1.事件處理器
2.異步代碼
3.服務端的渲染代碼
4.在error boundaries區域內的錯誤
在這個lifecycle method: componentDIdCatch(error,info) 里的類會變成一個 error boundary
class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false }; } componentDidCatch(error, info) { // Display fallback UI this.setState({ hasError: true }); // You can also log the error to an error reporting service logErrorToMyService(error, info); } render() { if (this.state.hasError) { // You can render any custom fallback UI return <h1>Something went wrong.</h1>; } return this.props.children; } }
然后你就可以像一個普通組件一樣使用它
<ErrorBoundary> <MyWidget /> </ErrorBoundary>
componentDidCatch()方法像JS的catch{}模塊一樣工作,但是對于組件,只有class類型的組件(class component)可以成為一個error boundaries,在實際上,大多數情況下你可能只需要在整個程序中定義一個error boundary組件,然后你就可以一直使用它了!
請注意error boundaries僅僅可以捕獲到在他們樹的層級下面的錯誤,而不能捕獲到本層級的錯誤,如果一個error boundaries渲染錯誤信息失敗了,那么這個錯誤將會傳播到一個在它層級上面,并且離它最近的error boundary 。這就像js的{}模塊的工作機制一樣。
ComponentDidCatch 參數
- error: 這是一個已經被拋出的錯誤
- info:這是一個componentStack key。這個屬性有關于拋出錯誤的組件堆的信息
componentDidCatch(error, info) { /* Example stack information: in ComponentThatThrows (created by App) in ErrorBoundary (created by App) in div (created by App) in App */ logComponentStackToMyService(info.componentStack);
觸發error boundaries后程序要走向哪里?
關于error boundaries的后續處理由你做主,你可能會指定一個最高等級的路由組件去給用戶標識某些地方出了問題,就像服務端的框架處理異常一樣,你也可以指定一個在錯誤邊界內的個人的小頁面讓整個程序不至于發生崩潰。
對于不能捕獲的錯誤的新處理方式
這種變化有一個重要的新含義,對于React 16,沒有被任何error boundary捕獲的錯誤將會導致整個React組件樹的崩潰。
我們對這個決定有爭論,但是在我們的經驗里,留下一個崩潰的UI界面比完全移除它要糟糕,例如,在一個產品比如聊天器中,留下一個崩壞的UI界面可能會導致某個人發送信息給一個并非他想要發送的人。同樣的,對于一個支付類的app來說,不要顯示任何東西顯然比顯示一個錯誤的金額數目要好。
這個改動意味著如果你遷移到React 16,你可能會發現一些以前沒有注意到的,并且是確確實實存在的在你程序中的異常,增加error boundaries會讓你在某些地方出現問題的時候可以提供更好的用戶體驗。
舉個例子,facebook的側邊欄,信息面板,對話記錄以及消息輸入框處于被分割開來的error boundaries中,如果在他們的UI子組件中發生了崩潰事件,那么其他的組件還可以正常運行。
我們同樣鼓勵你使用JS 錯誤報道服務(或者你自己建立一個),然后你就可以了解到這些未被處理的異常是如何發生的,接著解決他們。
在堆中跟蹤component
React 16 會把所有render過程中發生的錯誤打印給開發者,即使程序意外的包含了它。它不僅僅提供了錯誤信息和追蹤js堆,也提供了組件的堆路徑,現在你可以精確的看到組件樹中錯誤發生的地方。
你同樣可以在組件的堆追蹤中看到文件名字和行數,這是creat react app項目的默認配置
如果你沒有使用Create React App ,你也可以通過添加這個插件,手動的管理你的babel配置。注意:它必須嚴格的限制在開發過程中使用,生產過程一定要剔除。
注意: 在堆的追蹤中看到的組件名字取決于 Function.name屬性。如果你想要支持那些現在還沒有原生提供這些的瀏覽器和設備,比如ie11,consider including a?Function.name
?polyfill in your bundled application, such as?function.name-polyfill
. 否則,你必須明確的在你所有的組件中都設置displayName.
try/catch 如何?
try/catch是非常棒的但是它只在imperative code(命令式代碼)中起作用
try { showButton(); } catch (error) { // ... }
然而,react組件是聲明式的并且指定應該被渲染的內容
<Button />
Error boundaries保留了React的聲明式性質,并且擁有你期待的表現。比如,即使通過某個在樹的深層setState,在componentDidUpdate攔截中發生了錯誤,它也仍然會被正確的傳送到最近的error boundary。
Event Handlers怎么樣?
error boundaries并不能捕獲event handles中的異常。
React并不需要error boundaries從event handles中恢復錯誤。與render方法和lifecycle攔截不同的是,event Handles并不會在rendering期間發生。所以如果他們被拋出,React仍然知道怎么去渲染。
如果你需要捕獲event handler,使用普通的js代碼try/catch 聲明
class MyComponent extends React.Component { constructor(props) { super(props); this.state = { error: null }; } handleClick = () => { try { // Do something that could throw } catch (error) { this.setState({ error }); } } render() { if (this.state.error) { return <h1>Caught an error.</h1> } return <div onClick={this.handleClick}>Click Me</div> } }
注意以上代碼僅僅展示通常的js習慣,而沒有使用error boundaries。
React 15后的函數命名改變
React 15通過unstable_handleError方法
?包含了一些有限的error boundaries支持。這個方法現在已經不能運用,你需要使用compoentDIdCatch。
總結
原文鏈接:https://blog.csdn.net/a986597353/article/details/78469979
相關推薦
- 2022-07-16 Spring MVC重定向和轉發
- 2022-03-21 詳解C語言動態內存的分配_C 語言
- 2022-07-12 微信小程序(條件渲染和列表渲染)
- 2022-08-23 .net?core中的System.Buffers命名空間_基礎應用
- 2022-09-16 C#中Path類的使用方法_C#教程
- 2022-06-29 python人工智能tensorflow函數tensorboard使用方法_python
- 2022-04-05 debian:根據文件名稱,找到對應的包
- 2023-04-03 go語言之美迅速打rpm包實現詳解_Android
- 最近更新
-
- 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同步修改后的遠程分支