Skip to content

0823

Error Boundary

  • https://ko.legacy.reactjs.org/docs/error-boundaries.html

  • React Error Boundary는

  • 컴포넌트 트리의 어디서든 JavaScript 에러를 catch하고,

  • 그 에러를 기록하며,

  • 에러가 발생한 컴포넌트 트리 대신 fallback UI를 보여주는 컴포넌트다.

  • 사용 방법은 두 가지... 직접 클래스 컴포넌트를 만들거나, 라이브러리를 쓰거나.

  • 아래 예제로 사용 방법을 봐보자..

  • 공통으로 들어가는 BuggyComponent가 있다고 가정하자.

  • 이 컴포넌트는 일시적으로 counter 상태를 받아서 click me라는 버튼을 누를 때마다 counter가 업데이트 되도록 하는 컴포넌트고

  • click me 버튼을 3번 누르면 오류가 뜨게 할거다.

BuggyComponent

jsx
import { useState } from "react";

function BuggyComponent() {  
  const [counter, setCounter] = useState(0);

  if (counter === 3) {  
    throw new Error("I crashed!");  
  }

  return (  
    <div>  
      <p>Counter: {counter}</p>  
      <button onClick={() => setCounter(counter + 1)}>Click me</button>  
    </div>  
  );  
}

export { BuggyComponent };

라이브러리 쓰기

bash
npm i react-error-boundary
jsx
function ErrorFallback({ error, resetErrorBoundary }) {  
  return (  
    <div role="alert">  
      <h2>Something went wrong:</h2>  
      <pre>{error.message}</pre>  
      <button onClick={resetErrorBoundary}>Try again</button>  
    </div>  
  );  
}
jsx
import { ErrorBoundary } from 'react-error-boundary';  
function App() {  
  return (  
    <ErrorBoundary FallbackComponent={ErrorFallback}>  
      <BuggyComponent />  
    </ErrorBoundary>  
  );  
}

직접 구현하기

jsx
import React from "react";

class ErrorBoundary extends React.Component {  
  constructor(props) {  
    super(props);  
    this.state = { hasError: false, error: null };  
  }

  static getDerivedStateFromError() {  
    return { hasError: true };  
  }

  componentDidCatch(error, errorInfo) {  
    console.error("Error caught by boundary:", error, errorInfo);  
    this.setState({ error });  
  }

  render() {  
    if (this.state.hasError) {  
      return (  
        <div>  
          <h2>오류 발생</h2>  
          <p>  
            {this.state.error && this.state.error.toString()}  
          </p>  
        </div>  
      );  
    }

    return this.props.children;  
  }  
}

export { ErrorBoundary };
  • 왜 클래스로 상속 받아서 Error Boundary 컴포넌트를 구현해야 되는가? 훅으론 구현 못하나?
    • getDerviedStateFromError: fallback ui가 보이도록 상태를 업데이트 === 렌더링 단계에서 에러발생시 state 업데이트
    • componentDidCatch: 에러 리포팅 서비스에 에러를 기록 === commit render
    • 위 메서드들을 써야하니 hook으로 대체할 수 없고 class로 상속 받아서 써야된다.

의문

  • 그럼 error boundaray는 모든 error case를 처리할 수 있는가? => Xxxxx
    • Event Handlers 내부 에러
    • 비동기 코드 에러
    • SSR 에러
  • 는 처리 못한다.
  • 왜? 에러 바운더리는 리액트의 렌더링 사이클중 발생하는 에러만 캐치 할 수 있다.
    1. Event Handelr는 브라우저 이벤트고,
    2. 비동기 코드는 react 렌더링이 끝난 다음에 실행되는 코드고,
    3. 서버사이드렌더링은 서버 환경에서 실행되니까 모른다.