」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > GlobalErrorHandler:捕捉從 ErrorBoundary 手中落下的錯誤!

GlobalErrorHandler:捕捉從 ErrorBoundary 手中落下的錯誤!

發佈於2024-11-07
瀏覽:265

GlobalErrorHandler: Catch the errors that falls through ErrorBoundary

ErrorBoundary 是一個出色的工具,可以捕捉 React 元件拋出的錯誤。您可以根據錯誤本身的性質和位置提供自訂錯誤訊息。但並非所有拋出的錯誤都由 ErrorBoundary 處理!你用這些做什麼?

當考慮非同步錯誤和從 React 外部拋出的錯誤時,ErrorBoundary 不夠。為了緩解這個問題,我在我的應用程式中創建了我所說的 GlobalErrorHandler。一個功能元件,只需 A) 彈出一個錯誤對話框,告訴使用者出現問題,B) 將錯誤記錄到伺服器,以便我們調查並找到解決方案。

這個想法很簡單。我們希望在應用程式的根目錄中有一個 GlobalErrorHandler。該處理程序應該僅處理ErrorBoundary未捕獲的錯誤。更重要的是,它應該很容易被用戶忽略,我們應該假設該應用程式仍然可用。

因此策略是這樣的:預設情況下,除了渲染其子級之外,GlobalErrorHandler 根本不執行任何操作。但是,它設定了兩個事件偵聽器,偵聽瀏覽器中的所有錯誤和未處理的拒絕事件。然後它檢查錯誤,並查看它是否已被任何 ErrorBoundaries 處理。最後,如果情況並非如此,它會彈出一個對話框,告訴用戶某處出了問題,並讓用戶關閉該對話框並繼續使用該應用程式。

錯誤是否已處理

在 ErrorBoundary 處理之上使用不必要的對話框來困擾最終用戶之前,我們首先必須先詢問錯誤:您已經被處理了嗎?我的解決方案是在錯誤物件 isHandledByBoundary 上引入一個新欄位。這在 ErrorBoundary:
中設定為 true

  componentDidCatch(error: Error, errorInfo: ErrorInfo) {
    (error as any).isHandledByBoundary = true;
    ....
  }

在所有 ErrorBoundary 元件(以及處理未捕獲錯誤的其他機制)中使用此功能後,我們就準備好開始定義 GlobalErrorHandler。

裸露的骨架

然後我們可以建立 GlobalErrorHandler 的骨架。它直接呈現其子項,並且也呈現在其他地方定義的「ErrorDialog」。 (如果您想跨應用程式共用此元件,則 ErrorDialog 可以是 prop。)

import { useState, useEffect, ReactNode } from 'react';
import { ErrorDialog } from '../Components/ErrorDialog';

type Props = {
  children: ReactNode;
};

export function GlobalErrorHandler({ children }: Props) {
  const [error, setError] = useState(null);
  const [isDialogOpen, setDialogOpen] = useState(false);

  useEffect(() => {
    ....
  }, []);

  function handleCloseDialog() {
    setDialogOpen(false);
    setError(null);
  }

  return (
    
      {children}

      {isDialogOpen && error && (
        
      )}
    >
  );
}

我們現在唯一缺少的是錯誤處理本身,在 useEffect 中定義。

處理錯誤

本節中的所有程式碼都應位於 useEffect 函數內!

首先我們定義handleWindowError。這將被傳遞到視窗物件上的錯誤事件處理程序。這裡沒什麼神秘的,但請注意錯誤事件還包含有關來源、行號和列號的資訊。這可能具有收藏價值。

通常這些資訊也可以在錯誤物件中找到,但我需要對此進行更多的實證調查。也許我們總是應該保留錯誤事件報告的行號和列號?在這種情況下,我們還可以在 GlobalErrorHandler 中擁有一個狀態(並確保在記錄錯誤時發送該狀態)。

   function handleWindowError(
      message: string | Event,
      source?: string,
      lineno?: number,
      colno?: number,
      error?: Error
    ) {
      if (error && (error as any).isHandledByBoundary) {
        return true;
      }

      const errorMessage = error
        ? error
        : `Error: ${message} at ${source}:${lineno}:${colno}`;
      setError(errorMessage);
      setDialogOpen(true);
      return true;
    }

我們也將定義handleUnhandledRejection 處理程序。這是針對在承諾中引發的錯誤,但我們忘記寫 .catch() 子句。

    function handleUnhandledRejection(event: PromiseRejectionEvent) {
      setError(`Unhandled promise rejection: ${event.reason}`);
      setDialogOpen(true);
    }

然後我們需要做的就是設定偵聽器,並在 GlobalErrorHandler 不再呈現時刪除偵聽器:

    window.addEventListener('error', handleWindowError);
    window.addEventListener('unhandledrejection', handleUnhandledRejection);

    return () => {
      window.removeEventListener('error', handleWindowError);
      window.removeEventListener(
        'unhandledrejection',
        handleUnhandledRejection
      );
    };

return 語句當然是我們從我們提供給 useEffect 的函數中傳回的地方。這確保了我們在元件渲染時開始監聽事件並處理它們,並在元件不再渲染時停止。

因此,我們有一個 GlobalEventHandler,來處理 React 應用程式中那些討厭的錯誤,這些錯誤要么從非同步來源拋出,要么從 React 元件外部拋出!

版本聲明 本文轉載於:https://dev.to/lebbe/globalerrorhandler-catch-the-errors-that-falls-through-errorboundarys-fingers-3m5d?1如有侵犯,請聯絡[email protected]刪除
最新教學 更多>
  • 為什麼HTML無法打印頁碼及解決方案
    為什麼HTML無法打印頁碼及解決方案
    無法在html頁面上打印頁碼? @page規則在@Media內部和外部都無濟於事。 HTML:Customization:@page { margin: 10%; @top-center { font-family: sans-serif; font-weight: ...
    程式設計 發佈於2025-07-13
  • 如何有效地選擇熊貓數據框中的列?
    如何有效地選擇熊貓數據框中的列?
    在處理數據操作任務時,在Pandas DataFrames 中選擇列時,選擇特定列的必要條件是必要的。在Pandas中,選擇列的各種選項。 選項1:使用列名 如果已知列索引,請使用ILOC函數選擇它們。請注意,python索引基於零。 df1 = df.iloc [:,0:2]#使用索引0和1 ...
    程式設計 發佈於2025-07-13
  • 將圖片浮動到底部右側並環繞文字的技巧
    將圖片浮動到底部右側並環繞文字的技巧
    在Web設計中圍繞在Web設計中,有時可以將圖像浮動到頁面右下角,從而使文本圍繞它纏繞。這可以在有效地展示圖像的同時創建一個吸引人的視覺效果。 css位置在右下角,使用css float and clear properties: img { 浮點:對; ...
    程式設計 發佈於2025-07-13
  • Java為何無法創建泛型數組?
    Java為何無法創建泛型數組?
    通用陣列創建錯誤 arrayList [2]; JAVA報告了“通用數組創建”錯誤。為什麼不允許這樣做? 答案:Create an Auxiliary Class:public static ArrayList<myObject>[] a = new ArrayList<my...
    程式設計 發佈於2025-07-13
  • Go語言垃圾回收如何處理切片內存?
    Go語言垃圾回收如何處理切片內存?
    Garbage Collection in Go Slices: A Detailed AnalysisIn Go, a slice is a dynamic array that references an underlying array.使用切片時,了解垃圾收集行為至關重要,以避免潛在的內存洩...
    程式設計 發佈於2025-07-13
  • 為什麼不````''{margin:0; }`始終刪除CSS中的最高邊距?
    為什麼不````''{margin:0; }`始終刪除CSS中的最高邊距?
    在CSS 問題:不正確的代碼: 全球範圍將所有餘量重置為零,如提供的代碼所建議的,可能會導致意外的副作用。解決特定的保證金問題是更建議的。 例如,在提供的示例中,將以下代碼添加到CSS中,將解決餘量問題: body H1 { 保證金頂:-40px; } 此方法更精確,避免了由全局保證金重置...
    程式設計 發佈於2025-07-13
  • JavaScript計算兩個日期之間天數的方法
    JavaScript計算兩個日期之間天數的方法
    How to Calculate the Difference Between Dates in JavascriptAs you attempt to determine the difference between two dates in Javascript, consider this s...
    程式設計 發佈於2025-07-13
  • PHP未來:適應與創新
    PHP未來:適應與創新
    PHP的未來將通過適應新技術趨勢和引入創新特性來實現:1)適應云計算、容器化和微服務架構,支持Docker和Kubernetes;2)引入JIT編譯器和枚舉類型,提升性能和數據處理效率;3)持續優化性能和推廣最佳實踐。 引言在編程世界中,PHP一直是網頁開發的中流砥柱。作為一個從1994年就開始發展...
    程式設計 發佈於2025-07-13
  • 如何從PHP中的Unicode字符串中有效地產生對URL友好的sl。
    如何從PHP中的Unicode字符串中有效地產生對URL友好的sl。
    為有效的slug生成首先,該函數用指定的分隔符替換所有非字母或數字字符。此步驟可確保slug遵守URL慣例。隨後,它採用ICONV函數將文本簡化為us-ascii兼容格式,從而允許更廣泛的字符集合兼容性。 接下來,該函數使用正則表達式刪除了不需要的字符,例如特殊字符和空格。此步驟可確保slug僅包...
    程式設計 發佈於2025-07-13
  • Go語言如何動態發現導出包類型?
    Go語言如何動態發現導出包類型?
    與反射軟件包中的有限類型的發現能力相反,本文探索了替代方法,探索了在Runruntime。 go import( “ FMT” “去/進口商” ) func main(){ pkg,err:= incorter.default()。導入(“ time”) 如果er...
    程式設計 發佈於2025-07-13
  • 為什麼Microsoft Visual C ++無法正確實現兩台模板的實例?
    為什麼Microsoft Visual C ++無法正確實現兩台模板的實例?
    在Microsoft Visual C 中,Microsoft consions用戶strate strate strate strate strate strate strate strate strate strate strate strate strate strate strate st...
    程式設計 發佈於2025-07-13
  • 為什麼使用固定定位時,為什麼具有100%網格板柱的網格超越身體?
    為什麼使用固定定位時,為什麼具有100%網格板柱的網格超越身體?
    網格超過身體,用100%grid-template-columns 為什麼在grid-template-colms中具有100%的顯示器,當位置設置為設置的位置時,grid-template-colly修復了? 問題: 考慮以下CSS和html: class =“ snippet-code”> ...
    程式設計 發佈於2025-07-13
  • 大批
    大批
    [2 數組是對象,因此它們在JS中也具有方法。 切片(開始):在新數組中提取部分數組,而無需突變原始數組。 令ARR = ['a','b','c','d','e']; // USECASE:提取直到索引作...
    程式設計 發佈於2025-07-13
  • Python讀取CSV文件UnicodeDecodeError終極解決方法
    Python讀取CSV文件UnicodeDecodeError終極解決方法
    在試圖使用已內置的CSV模塊讀取Python中時,CSV文件中的Unicode Decode Decode Decode Decode decode Error讀取,您可能會遇到錯誤的錯誤:無法解碼字節 在位置2-3中:截斷\ uxxxxxxxx逃脫當CSV文件包含特殊字符或Unicode的路徑逃...
    程式設計 發佈於2025-07-13
  • 如何有效地轉換PHP中的時區?
    如何有效地轉換PHP中的時區?
    在PHP 利用dateTime對象和functions DateTime對象及其相應的功能別名為時區轉換提供方便的方法。例如: //定義用戶的時區 date_default_timezone_set('歐洲/倫敦'); //創建DateTime對象 $ dateTime = ne...
    程式設計 發佈於2025-07-13

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3