오류 경계 반응에서 오류를 우아하게 처리하다

React에서 잘못된 경계를 실현하는 선결 조건

  • 은 실행 시 오류와 컴파일 시 오류 등 오류 유형을 알고 있습니다.
  • 클래스 기반 구성 요소 지식
  • 잘못된 보초 계정 기록
  • 이 박문이 포괄하는 주제

  • 은react에서 잘못된 경계를 실현하는 체계 구조 설계 모델에 사용된다.
  • 처음부터 잘못된 경계를 실행합니다.
  • 오류 경계 포획의 오류 유형.
  • react 오류 경계를 사용할 때 자주 발생하는 문제입니다.
  • 이 구조에 반응했다.
  • 제3자 오류 기록 도구의 실현, 예를 들어sentry.
  • 우리의 잘못된 경계 구조:

  • react에서 모든 오류 경계는 클래스 기반 구성 요소로 구성됩니다.
  • 오류 경계는 우아한 방법으로 이러한 방법을 사용하면 오류를 더욱 효과적으로 포착할 수 있다.
  • 은 JSX 생태계의 trycatch 블록으로 간주할 수 있습니다.
  • 다음
  • 은react에서 잘못된 경계의 간단한 예입니다
  • const App = () => {
    
      return (
        <div>
        <h1>Counter Example</h1>
          <ErrorBoundary fallBackUIComponent={<FallBackUI />}>
            <BuggyComponent />
          </ErrorBoundary>
        </div>
      );
    }
    
  • 보시다시피, ErrorBoundary 구성 요소는 오류를 초래할 수 있는 구성 요소의 부모 구성 요소로 배치됩니다.
  • BuggyComponent에서 런타임 오류가 발생할 때마다 최근 오류 경계(ErrorBoundary 구성 요소)에서 오류를 캡처하고 예비(fallback) UI를 표시합니다.다음은 이런 상황을 설명할 것이다.
  • 오류 경계는 클래스 기반 구성 요소이기 때문에 오류를 포착하는 방법이 있습니다.다음은 ErrorBoundary의 아키텍처입니다.

  • 잘못된 경계 구현:


  • 잘못된 경계를 실시하기 전에 다음과 같은 몇 가지를 기억해야 한다.
  • 오류 경계는 항상 class 기반 구성 요소입니다.
  • 은 다음 두 가지 방법으로 오류를 포착합니다.
  • static getDerivedStateFromError(): DOM이 준비되기 전(구성 요소의 구현 단계에서) 실행되는 정적 방법입니다.서브어셈블리에서 오류가 발생할 때마다 호출됩니다.
  • componentDidCatch(): 하위 구성 요소가 오류를 던질 때마다 이 함수를 호출합니다.commit 단계, 즉 DOM이 준비되면 이 구성 요소를 호출합니다.구성 요소의 부작용을 수행하는 데 사용할 수 있습니다.두 개의 매개변수를 수신합니다.
  • error - 던지고 있는 오류입니다.
  • info - component Stack이 있는 대상입니다. 어떤 구성 요소가 오류를 냈는지 알려 줍니다.
  • 이제 잘못된 경계를 실현할 수 있습니다.다음 코드에서는 클래스 기반 react 오류 경계를 보여 줍니다.
  • class ErrorBoundary extends React.Component {
      constructor(props){
        super(props);
        this.state = {
          hasError: false
        };
      }
       static getDerivedStateFromError(error) {
        // Update state so the next render will show the fallback UI.
        return { hasError: true };
      }
      componentDidCatch(error, errorInfo) {
        //Can be used to log to any logging service like sentry
         console.log("Catched error", errorInfo);
      }
    
      render(){
        if(this.state.hasError){
          return(
            // <h3>Something went wrong!</h3>
            //Can be a static or a fall-back component passed as a prop.
            this.props.fallBackUIComponent
          );
        }
    
        return this.props.children;
      }
    }
    
    위 구현 시 주의해야 할 사항은 다음과 같습니다.
  • getDerivedStateFromError은 구성 요소를 업데이트하는 상태로 값을 되돌려줍니다. 이 경우 hasError은true로 설정됩니다.
  • componentDidCatch은 오류와 잘못된 스택 추적도 포착합니다.이것은 구성 요소의 제출 단계에서 발생할 것입니다.
  • 마지막으로 render 함수에서 hasError 상태가 true이면 우리가 도구로 전달하는 반환 구성 요소를 출력합니다.그렇지 않으면 children으로 돌아갑니다.
    이 구성 요소의 사용은 매우 간단하다.문제의 구성 요소를 ErrorBoundary으로 포장하면 하위 세대가 던진 오류를 포착할 수 있습니다.다음 예제에서는 사용법을 명확하게 보여 줍니다.
    //Component for fallback UI:
    const FallBackUI = () => {
      return (
        <>
        <h3>Something went wrong</h3>
          </>
      );
    }
    
    const BuggyComponent = () => {
      const [count, setCount] = React.useState(0);
    
      const increaseCounter = () => {
        setCount(preVal => preVal + 1);
      }
        if(count === 5) {
          throw new Error("Crashing the app!!");
        }
    
      return (
        <>
          <div className="counter--block">
            <span>Counter</span>
            <span>{count}</span>
          </div>
          <button onClick={increaseCounter}>Increase count</button>
          </>
      );
    }
    
    const App = () => {
    
      return (
        <div>
        <h1>Counter Example</h1>
          <ErrorBoundary fallBackUIComponent={<FallBackUI />}>
            <BuggyComponent />
          </ErrorBoundary>
        </div>
      );
    }
    
    ReactDOM.render(
    <App />
      ,
      document.getElementById("root")
    );
    

    오류 경계 포획 오류 유형


  • React's Error Boundary 문서에 따르면 이것은 구성 요소의 생명 주기에 발생하는 오류만 포획한다. 즉, 운행 시 오류만 포획한다.

  • 다음에 언급한 오류는 react의 오류 경계에 포착되지 않았습니다.

    Event handlers (learn more)

    Asynchronous code (e.g. setTimeout or requestAnimationFrame callbacks)

    Server side rendering

    Errors thrown in the error boundary itself (rather than its children)


  • react 오류 경계를 사용할 때 자주 발생하는 문제:

    error boundary이 일을 하지 않는 데는 몇 가지 이유가 있을 수 있다.
    이 중 일부는 다음과 같습니다.

    경계 어셈블리의 배치가 잘못되었습니다.


    일부 상황에서, 우리는 오류를 포착하기 위해 항상 ErrorBoundary의 구성 요소 포장을 사용해야 한다는 것을 잊어버렸다.다음 예는 명확한 이해를 제공할 것이다.
    카운터 값이 5에 도달하면 오류가 발생하는 구성 요소를 고려합니다.
    const BuggyComponent = () => {
      const [count, setCount] = React.useState(0);
    
      const increaseCounter = () => {
        setCount(preVal => preVal + 1);
      }
        if(count === 5) {
          throw new Error("Crashing the app!!");
        }
    
      return (
        <>
          <div className="counter--block">
            <span>Counter</span>
            <span>{count}</span>
          </div>
          <button onClick={increaseCounter}>Increase count</button>
          </>
      );
    }
    
    아래와 같이 오류 경계를 배치하면 ErrorBoundary 구성 요소가 오류를 포획하는 것을 영원히 허용하지 않습니다. 왜냐하면 BuggyComponentErrorBoundary으로 포장된 것이 아니라 ErrorBoundary으로 포장된 것이기 때문입니다.
    return (
        <ErrorBoundary>
          <div className="counter--block">
            <span>Counter</span>
            <span>{count}</span>
          </div>
          <button onClick={increaseCounter}>Increase count</button>
          </ErrorBoundary>
      );
    
    그리고 이 두 가지 방법 모두 BuggyComponent이 던진 오류를 포착하지 못할 것이다.이 목표를 실현하기 위해서 우리는 이렇게 할 수 있다.
    const App = () => {
    
      return (
        <div>
        <h1>Counter Example</h1>
          <ErrorBoundary>
            <BuggyComponent />
          </ErrorBoundary>
        </div>
      );
    }
    
    현재 ErrorBoundary은 잘못된 경계에 포장되어 있기 때문에 BuggyComponent에서 던진 오류를 포착할 것이다.

    이벤트 프로세서에서 새 오류를 제거하려면:


    위의 용례에서 보듯이 계수가 5에 달할 때마다 새로운 오류가 발생합니다.
    참고: 이 작업에 사용되는 if 블록은 어셈블리의 렌더링 단계에 배치되므로 ErrorBoundary 캡처 오류에 대해 유효한 케이스를 생성합니다.
    const BuggyComponent = () => {
      const [count, setCount] = React.useState(0);
    
      const increaseCounter = () => {
        setCount(preVal => preVal + 1);
      }
        if(count === 5) {
          throw new Error("Crashing the app!!");
        }
    
      return (
        <>
          <div className="counter--block">
            <span>Counter</span>
            <span>{count}</span>
          </div>
          <button onClick={increaseCounter}>Increase count</button>
          </>
      );
    }
    
    const App = () => {
    
      return (
        <div>
        <h1>Counter Example</h1>
          <ErrorBoundary>
            <BuggyComponent />
          </ErrorBoundary>
        </div>
      );
    }
    
    그러나 if 블록을 increaseCounter 함수에 넣으면 같은 방법은 작용하지 않는다.이러한 상황을 보여주기 위해 상술한 예시를 수정하였다.
    const BuggyComponent = () => {
      const [count, setCount] = React.useState(0);
    
      const increaseCounter = () => {
        setCount(preVal => preVal + 1);
        if(count === 5) {
          throw new Error("Crashing the app!!");
        }
      }
    
      return (
        <>
          <div className="counter--block">
            <span>Counter</span>
            <span>{count}</span>
          </div>
          <button onClick={increaseCounter}>Increase count</button>
          </>
      );
    }
    
    const App = () => {
    
      return (
        <div>
        <h1>Counter Example</h1>
          <ErrorBoundary>
            <BuggyComponent />
          </ErrorBoundary>
        </div>
      );
    }
    

    대체 패키지:오류 경계 반응

    react-error-boundary은 매우 인상적인 패키지입니다.이것은 이벤트 처리 프로그램이 던진 오류, 비동기 코드 등 오류를 포착할 수 없기 때문에react의 오류 경계가 직면하는 대부분의 도전을 해결했다.
    자세한 내용은 패키지의 github readme을 참조하십시오.
    다음은 위 예제의 구현이지만 react-error-boundary을 사용합니다.
    import {ErrorBoundary} from 'react-error-boundary';
    
    function ErrorFallback({error}) {
      return (
        <div role="alert">
          <p>Something went wrong:</p>
          <pre style={{color: 'red'}}>{error.message}</pre>
        </div>
      )
    }
    
    const BuggyCounter = () => {
      const [count, setCount] = React.useState(0);
    
      const handleIncrement = () => {
        setCount(preVal => preVal + 1);
      }
    
      if(count === 5){
          throw new Error("New Crashing Seq. Initiated");
      }
    
      return(
        <div className="counter--block">
          <span>Count</span>
          <span>{count}</span>
          <button onClick={handleIncrement}>Increment count</button>
          </div>
      );
    }
    const App = () => {
      return(
        <>
        <h1>Counter Example</h1>
        <ErrorBoundary FallbackComponent={ErrorFallback}>
    
            <BuggyCounter />
        </ErrorBoundary>
          </>
      )
    }
    
    ReactDOM.render(
      <App/>,
      document.getElementById("root")
    );
    

    제3자 오류 기록 도구의 실현


    오류 로그 기록은 모든 응용 프로그램 개발 과정의 관건적인 부분이다.그것은 응용 프로그램 테스트 과정에서 포착할 수 없는 오류를 분석하고 조직하는 데 도움을 줄 수 있다.이러한 오류 로그 도구는 클라이언트 기기/브라우저에서 발생하는 오류를 감시하는 데 사용됩니다.
    잘못된 기록에 대해 말하자면, 나는 sentry.io이 다행이라는 것을 발견하였다.그것은 인상적인 문서를 가지고 있으며 자바, JS, React, React Native 등 다양한 기술 창고에 광범위한 지원을 제공한다.
    다음은 상술한 예시의 수정 예시이다.
    import React from "react";
    import ReactDOM from "react-dom";
    import * as Sentry from "@sentry/react";
    import App from "./App";
    
    Sentry.init({ dsn: "https://[email protected]/0" });
    
    const BuggyCounter = () => {
        const [counter, setCounter] = useState(0);
    
        return (
            <>
            <div className="counter--value">
                {counter}
            </div>
            <div>
                <button
                  className="counter--button"
                  onClick={() => { throw new Error("New Test Error")}}>
                    increment count
                 </button>
            </div>
            </>
        )
    }
    
    const App = () => {
      return (
        <Sentry.ErrorBoundary fallback={"An error has occurred"}>
          <BuggyCounter />
        </Sentry.ErrorBoundary>
      );
    }
    
    ReactDOM.render(<App />, document.getElementById("root"));
    
    // Can also use with React Concurrent Mode
    // ReactDOM.createRoot(document.getElementById('root')).render(<App />);
    
    
    이 예에서는 먼저 init 함수를 사용하여 Sentry 인스턴스를 초기화해야 합니다.
    Sentry.init({ dsn: "https://[email protected]/0" });
    
    참고: dsn은 SDK에서 이벤트를 어디로 보낼지 알려주는 데이터 소스 이름입니다.
    또한 Sentry는 자체 오류 경계 구성 요소를 제공합니다.
    import * as Sentry from "@sentry/react";
    
    const App = () => {
      return (
        <Sentry.ErrorBoundary fallback={"An error has occurred"}>
          <BuggyCounter />
        </Sentry.ErrorBoundary>
      );
    }
    
    다음 블로그 글에서 사용할 코드를 찾을 수 있습니다.
  • react 오류 경계를 처음부터 실행합니다.
    https://codepen.io/keyurparalkar/pen/LYWJKvm?editors=0010
  • react-error-boundary 패키지를 사용하여react 오류 경계를 실현:
    https://codepen.io/keyurparalkar/pen/bGqQNJe
  • 언제든지 연락 주세요@

    좋은 웹페이지 즐겨찾기