>  기사  >  웹 프론트엔드  >  GlobalErrorHandler: ErrorBoundary의 손가락 사이로 떨어지는 오류를 잡아보세요!

GlobalErrorHandler: ErrorBoundary의 손가락 사이로 떨어지는 오류를 잡아보세요!

Linda Hamilton
Linda Hamilton원래의
2024-10-21 20:39:29552검색

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가 대신 소품이 될 수 있습니다.)

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

type Props = {
  children: ReactNode;
};

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

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

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

  return (
    <>
      {children}

      {isDialogOpen && error && (
        <ErrorDialog
          actionName="Unhandled error"
          error={error}
          loggFeilmelding={true}
          onClose={handleCloseDialog}
        />
      )}
    </>
  );
}

현재 부족한 유일한 것은 useEffect 내에 정의된 오류 처리 자체입니다.

오류 처리

이 섹션의 모든 코드는 useEffect 함수 내에 위치해야 합니다!

먼저 handlerWindowError를 정의합니다. 이는 창 개체의 오류 이벤트 처리기로 전달됩니다. 여기에는 신비한 내용이 없지만 오류 이벤트에는 소스, 줄 번호 및 열 번호에 대한 정보도 포함되어 있습니다. 소장 가치가 있는 자료입니다.

보통 이 정보는 오류 개체 내에서도 발견되지만 이에 대해 좀 더 실증적인 조사가 필요합니다. 아마도 오류 이벤트에 의해 보고된 대로 줄과 열 번호를 항상 유지해야 할까요? 이 경우 GlobalErrorHandler 내에서 이에 대한 상태를 가질 수도 있습니다(오류를 기록할 때 이 상태가 전송되는지 확인하세요).

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

handleUnhandledRejection 핸들러도 정의하겠습니다. 이는 Promise 내에서 발생하는 오류에 대한 것이지만 .catch() 절을 작성하는 것을 잊어버렸습니다.

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

type Props = {
  children: ReactNode;
};

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

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

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

  return (
    <>
      {children}

      {isDialogOpen && error && (
        <ErrorDialog
          actionName="Unhandled error"
          error={error}
          loggFeilmelding={true}
          onClose={handleCloseDialog}
        />
      )}
    </>
  );
}

그런 다음 우리가 해야 할 일은 리스너를 설정하고 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;
    }

반환 문은 물론 우리가 useEffect를 제공하는 함수에서 반환되는 곳입니다. 이렇게 하면 이벤트 수신을 시작하고 구성 요소가 렌더링될 때 이벤트를 처리하고 구성 요소가 더 이상 렌더링되지 않을 때 중지됩니다.

따라서 비동기 소스에서 발생하거나 React 구성 요소 외부에서 발생하는 React 애플리케이션의 성가신 오류를 처리하기 위한 GlobalEventHandler가 있습니다!

위 내용은 GlobalErrorHandler: ErrorBoundary의 손가락 사이로 떨어지는 오류를 잡아보세요!의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.