欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

封裝一個最簡單ErrorBoundary組件處理react異常

 更新時間:2021年04月15日 16:58:49   作者:blazer_id  
這篇文章主要介紹了一個處理react異常的ErrorBoundary組件,簡單實用,代碼詳細,對這個組件感興趣的朋友可以參考下

前言

從 React 16 開始,引入了 Error Boundaries 概念,它可以捕獲它的子組件中產(chǎn)生的錯誤,記錄錯誤日志,并展示降級內(nèi)容,具體 官網(wǎng)地址

錯誤邊界避免一個組件錯誤導致整個頁面白屏不能使用等情況,使用優(yōu)雅降級的方式呈現(xiàn)備用的 UI,錯誤邊界可以在渲染期間、生命周期和整個組件樹的構(gòu)造函數(shù)中捕獲錯誤。自 React 16 起,任何未被錯誤邊界捕獲的錯誤將會導致整個 React 組件樹被卸載

ErrorBoundary 意義

  • 某些 UI 崩潰,不至于整個 webapp 崩潰

在瀏覽頁面時,由于后端返回異?;蛘咔岸说哪承╁e誤校驗,會導致用戶體驗很差,你想想,你帶著老婆,坐著火車,吃著火鍋唱著歌,突然被麻匪劫了,突然就報錯了,有些場景下,比如正在設置金額,或者查看關鍵頁面時,這樣的體驗就會很糟糕,比如你游戲充值了 500,結(jié)果由于接口原因顯示出來充值NaN,這種顯示比不顯示還讓人苦惱,不過相信大家對 JS 異常捕獲很熟悉了,try-catch 一包業(yè)務代碼就收工了。不過,在組件里對異常捕獲,需要用到的是 React 提供的 Error Boundary 錯誤邊界特性,用 componentDidCatch 鉤子來對頁面異常進行捕獲,以至于不會將異常擴散到整個頁面,有效防止頁面白屏。

官網(wǎng)如何實現(xiàn) 

👉 如果一個 class 組件中定義了 static getDerivedStateFromError() 或 componentDidCatch() 這兩個生命周期方法中的任意一個(或兩個)時,那么它就變成一個錯誤邊界。當拋出錯誤后,請使用 static getDerivedStateFromError() 渲染備用 UI ,使用 componentDidCatch() 打印錯誤信息 👈

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }
  static getDerivedStateFromError(error) {
    // 更新 state 使下一次渲染能夠顯示降級后的 UI
    return { hasError: true };
  }
  componentDidCatch(error, errorInfo) {
    // 你同樣可以將錯誤日志上報給服務器
    logErrorToMyService(error, errorInfo);
  }
  render() {
    if (this.state.hasError) {
      // 你可以自定義降級后的 UI 并渲染
      return <h1>Something went wrong.</h1>;
    }
    return this.props.children;
  }
}

然后你可以將它作為一個常規(guī)組件去使用:

<ErrorBoundary>
  <MyWidget />
</ErrorBoundary>

錯誤邊界的工作方式類似于 JavaScript 的 catch {},不同的地方在于錯誤邊界只針對 React 組件。只有 class 組件才可以成為錯誤邊界組件。大多數(shù)情況下, 你只需要聲明一次錯誤邊界組件, 并在整個應用中使用它,在使用時被包裹組件出現(xiàn)的錯誤或者throw new Error()拋出的異常都可以被錯誤邊界組件捕獲,并且顯示出兜底 UI

封裝一個可配置的 ErrorBoundary 

了解了官網(wǎng)實現(xiàn)錯誤邊界組件的方法,我們可以封裝一個ErrorBoundary組件,造一個好用的輪子,而不是直接寫死return <h1>Something went wrong</h1>,學習了react-redux原理后我們知道可以用高階組件來包裹react組件,將store中的數(shù)據(jù)和方法全局注入,同理,我們也可以使用高階組件包裹使其成為一個能夠錯誤捕獲的 react 組件

1.創(chuàng)造一個可配置的 ErrorBoundary 類組件

相比與官網(wǎng)的 ErrorBoundary,我們可以將日志上報的方法以及顯示的 UI 通過接受傳參的方式進行動態(tài)配置,對于傳入的UI,我們可以設置以react組件的方式 或 是一個React Element進行接受,而且通過組件的話,我們可以傳入?yún)?shù),這樣可以在兜底 UI 中拿到具體的錯誤信息

  • componentDidCatch() : 錯誤日志處理的鉤子函數(shù)
  • static getDerivedStateFromError() : 它將拋出的錯誤作為參數(shù),并返回一個值以更新 state
class ErrorBoundary extends React.Component {
  state = { error: false };
  static getDerivedStateFromError(error) {
    return { error };
  }
  componentDidCatch(error, errorInfo) {
    if (this.props.onError) {
      //上報日志通過父組件注入的函數(shù)進行執(zhí)行
      this.props.onError(error, errorInfo.componentStack);
    }
  }
  render() {
    const { fallback, FallbackComponent } = this.props;
    const { error } = this.state;
    if (error) {
      const fallbackProps = { error };
      //判斷是否為React Element
      if (React.isValidElement(fallback)) {
        return fallback;
      }
      //組件方式傳入
      if (FallbackComponent) {
        return <FallbackComponent {...fallbackProps} />;
      }
      throw new Error("ErrorBoundary 組件需要傳入兜底UI");
    }
    return this.props.children;
  }
}

這樣就可以對兜底UI顯示和錯誤日志進行動態(tài)獲取,使組件更加靈活,但是又有一個問題出現(xiàn),有時候會遇到這種情況:服務器突然 503、502 了,前端獲取不到響應,這時候某個組件報錯了,但是過一會又正常了。比較好的方法是用戶點一下被ErrorBoundary封裝的組件中的一個方法來重新加載出錯組件,不需要重刷頁面,這時候需要兜底的組件中應該暴露出一個方法供ErrorBoundary進行處理

1.在 ErrorBoundary 中添加方法,檢測是否有注入重置方法,如果有重置方法就執(zhí)行并且重置 state 中的 error,使其錯誤狀態(tài)為 false

resetErrorBoundary = () => {
  if (this.props.onReset) this.props.onReset();
  this.setState({ error: false });
};

2.在 render 中添加函數(shù)組件類型進行渲染,可以將重置的方法以及錯誤信息當做參數(shù)進行傳遞到當前組件進行處理

 render() {
    const { fallback, FallbackComponent, fallbackRender } = this.props;
    const { error } = this.state;
    if (error) {
      const fallbackProps = {
        error,
        resetErrorBoundary: this.resetErrorBoundary,
      };
      ...
      if (typeof fallbackRender === "function")return fallbackRender(fallbackProps);
      ...
    }
    return this.props.children;
  }

2.將 ErrorBoundary 通過高階函數(shù)進行包裹返回

import React from "react";
import DefaultErrorBoundary from "./core";
const catchreacterror = (Boundary = DefaultErrorBoundary) => InnerComponent => {
  return props => (
    <Boundary {...props}>
      <InnerComponent {...props} />
    </Boundary>
  );
};

使用&測試 

通過一個點擊自增的 Demo,當數(shù)字到達某值,拋出異常,這里分別對 class 組件和 Function 組件作為發(fā)起異常的組件進行測試

  • 發(fā)起異常的組件
//Function組件
const fnCount1 = ({ count }) => {
  if (count == 3) throw new Error("count is three");
  return <span>{count}</span>;
};
//Class組件
class fnCount2 extends React.Component {
  render() {
    const { count } = this.props;
    if (count == 2) throw new Error("count is two");
    return <span>{count}</span>;
  }
}
  • 處理錯誤異常的函數(shù)組件
const errorbackfn = ({ error: { message }, resetErrorBoundary }) => (
  <div>
    <p>出錯啦</p>
    <pre>{message}</pre>
    <button onClick={resetErrorBoundary}>Try again</button>
  </div>
);
  • 處理錯誤異常的普通組件
const errorbackcom = () => <h1>出錯啦,不可撤銷</h1>;
  • 測試組件
//對發(fā)起異常的組件進行包裹處理,返回一個可以處理錯誤編輯的高階組件
const SafeCount1 = catchreacterror()(fnCount1);
const SafeCount2 = catchreacterror()(fnCount2);
//測試主組件
const App = () => {
  const [count, setCount] = useState(0);
  const ListenError = (arg, info) => console.log("出錯了:" + arg.message, info); //錯誤時進行的回調(diào)
  const onReset = () => setCount(0); //點擊重置時進行的回調(diào)
  return (
    <div className="App">
      <section>
        <button onClick={() => setCount(count => count + 1)}>+</button>
        <button onClick={() => setCount(count => count - 1)}>-</button>
      </section>
      <hr />
      <div>
        Class componnet:
        <SafeCount2
          count={count}
          fallbackRender={errorbackfn}
          onReset={onReset}
          onError={ListenError}
        />
      </div>
      <div>
        Function componnet:
        <SafeCount1
          count={count}
          FallbackComponent={errorbackcom}
          onError={ListenError}
        />
      </div>
    </div>
  );
};

大功告成!

遇到的問題&總結(jié) 

有很多時候 react 錯誤邊界不是萬能的比如

  • 事件錯誤

上面 this.o 不存在,會報錯,window.onerror 可以捕獲,但是錯誤邊界捕獲不到。

  • 異步代碼

服務端渲染 和 錯誤邊界自己的錯誤

總結(jié)

  • 抽離組件 ✔
  • 錯誤反饋 ✔
  • UI 抽離 ✔
  • 錯誤重置 ✔
  • 抽離 hook 模式 ✖
  • 服務端 ✖

至此,謝謝各位在百忙之中點開這篇文章,希望對你們能有所幫助,相信你對 react 中的錯誤邊界有了大概的認實,也會編寫一個簡單的ErrorBoundary總的來說優(yōu)化的點還有很多,如有問題歡迎各位大佬指正。更多關于ErrorBoundary,react的資料請關注腳本之家其它相關文章,希望大家以后多多支持腳本之家!

相關文章

  • 深入理解React?State?原理

    深入理解React?State?原理

    本文主要介紹了React?State?原理,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • React如何使用sortablejs實現(xiàn)拖拽排序

    React如何使用sortablejs實現(xiàn)拖拽排序

    這篇文章主要介紹了React如何使用sortablejs實現(xiàn)拖拽排序問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • React路由封裝的實現(xiàn)淺析

    React路由封裝的實現(xiàn)淺析

    路由是React項目中相當重要的概念,對于功能較為復雜的網(wǎng)頁來說,必然會涉及到不同功能間的頁面跳轉(zhuǎn),本篇文章將對React官方維護的路由庫React-Router-Dom的使用和常用組件進行講解,同時對路由組件傳遞param參數(shù)的方式進行講解,希望對各位讀者有所參考
    2022-08-08
  • 使用 React 和 Threejs 創(chuàng)建一個VR全景項目的過程詳解

    使用 React 和 Threejs 創(chuàng)建一個VR全景項目的過程詳解

    這篇文章主要介紹了使用 React 和 Threejs 創(chuàng)建一個VR全景項目的過程詳解,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-04-04
  • 歸納總結(jié)Remix?表單常用方法及示例詳解

    歸納總結(jié)Remix?表單常用方法及示例詳解

    這篇文章主要為大家歸納總結(jié)了Remix?表單常用方法及示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-03-03
  • React中使用react-json-view展示JSON數(shù)據(jù)的操作方法

    React中使用react-json-view展示JSON數(shù)據(jù)的操作方法

    react-json-view是一個用于顯示和編輯javascript數(shù)組和JSON對象的React組件,本文給大家分享React中使用react-json-view展示JSON數(shù)據(jù)的操作方法,感興趣的朋友一起看看吧
    2023-12-12
  • react koa rematch 如何打造一套服務端渲染架子

    react koa rematch 如何打造一套服務端渲染架子

    這篇文章主要介紹了react koa rematch 如何打造一套服務端渲染架子,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-06-06
  • React中引用CSS方式及寫法大全(三種方式)

    React中引用CSS方式及寫法大全(三種方式)

    在React中引用CSS的方法有多種,可以根據(jù)個人的喜好和項目的需求來選擇,本文主要介紹了React中引用CSS方式及寫法大全,感興趣的可以了解一下
    2023-10-10
  • React的三大屬性你都知道嗎

    React的三大屬性你都知道嗎

    這篇文章主要為大家詳細介紹了React的三大屬性,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-02-02
  • React?Hooks項目實戰(zhàn)

    React?Hooks項目實戰(zhàn)

    React?Hooks是React?16.8版本引入的新特性,它使得在函數(shù)組件中也能夠使用狀態(tài)(state)和其他React特性,本文就來詳細介紹一下React?Hooks項目實戰(zhàn),感興趣的可以了解一下
    2023-11-11

最新評論