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 중국어 웹사이트의 기타 관련 기사를 참조하세요!