Error Boundary

숭이·2022년 3월 21일
0

Error Boundary

React 16 이전의 버전에서는 UI 일부분에 존재하는 자바스크립트 에러가 전체 애플리케이션을 중단시켰습니다.

이를 해결하기 위해 React 16에서는 Error Boundary라는 새로운 개념이 도입되었습니다.

Error Boundary란 ?

하위 컴포넌트 트리의 어디에서든 자바스크립트 에러를 기록하며, 깨진 컴포넌트 트리 대신 Fallback UI를 보여주는 React 컴포넌트 입니다.

 -> 전체 어플리케이션이 중단되고, 아무것도 없는 흰 화면 대신 Fallback UI가 렌더링 됩니다.

렌더링 도중 생명주기 메서드 및 그 아래있는 전체 트리에서 에러를 잡아냅니다.

Error Boundary는 자바스크립트의 try().catch() 구문과 유사하게 동작하지만 컴포넌트에 적용됩니다.

 -> 다시말하면 오직 컴포넌트만이 에러 경계가 될 수 있습니다.

getDerivedStateFromError

static getDerivedStateFromError()는 하위의 자손 컴포넌트에서 오류가 발생했을 때 호출됩니다.

이 메서드는 매개변수로 오류를 전달받고, 갱신된 state 값을 반드시 반환해야 합니다.

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

  static getDerivedStateFromError(error) {
    // state를 갱신하여 다음 렌더링에서 대체 UI를 표시합니다.
    // 갱신돤 state 값을 return 하는 것은 필수입니다.
    return { hasError: true };
  }

  render() {
    if (this.state.hasError) {
      // 별도로 작성한 대체 UI를 렌더링할 수도 있습니다.
      return <h1>Something went wrong.</h1>;
    }

    return this.props.children;
  }
}

componentDidCatch

자손 컴포넌트에서 오류가 발생했을 때 호출되며, 2개의 매개변수를 전달받습니다.
1. error - 발생한 오류
2. info - 어떤 컴포넌트가 오류를 발생시켰는지에 대한 정보를 포함한 componentStack 키를 가지고 있는 객체

getDerivedStateFromError 와 componentDidCatch 차이점

getDerivedStateFromError - render 단계에서 호출되므로, 부수효과를 발생시키면 안됩니다.

componentDidCatch - commit 단계에서 호출되므로 부수효과를 발생시켜도 됩니다. 부수효과란 오류 로그 기록등을 의미합니다.

  componentDidCatch(error, info) {
    // Example "componentStack":
    //   in ComponentThatThrows (created by App)
    //   in ErrorBoundary (created by App)
    //   in div (created by App)
    //   in App
    logComponentStackToMyService(info.componentStack);
  }

Error Boundary 예제코드

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

  static getDerivedStateFromError(error) {
    // 다음 렌더링에서 폴백 UI가 보이도록 상태를 업데이트 합니다.
    return { hasError: true };
  }

  componentDidCatch(error, errorInfo) {
    // 에러 리포팅 서비스에 에러를 기록할 수도 있습니다.
    logErrorToMyService(error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      // 폴백 UI를 커스텀하여 렌더링할 수 있습니다.
      return <h1>Something went wrong.</h1>;
    }

    return this.props.children;
  }
}

Error Boundary의 한계

  • Error Boundary는 다음과 같은 에러는 포착하지 않습니다.

    1. 이벤트 핸들러에서의 에러
    2. 비동기적 코드에서의 에러
    3. 서버사이드 렌더링에서의 에러
    4. 자식에서가 아닌, 에러 경계 자체에서 발생하는 에러
  • React 공식문서에 따르면 getDerivedStateFromError, componentDidCatch 생명주기에 해당하는 Hook은 아직 없지만, 곧 추가할 계획이라고 합니다.

react-error-boundary

  • FallbackComponent
    Error가 발생하였을 때 보여지는 component 입니다.
    'error', 'resetErrorBoundary' props를 가질 수 있습니다.

    • 'error' : 발생한 Error
    • 'resetErrorBoundary' : error boundary의 state를 리셋시킨다.(새로고침 버튼같은 것 만들때 유용하다고 함)
  • FallbackRender
    inline으로 fallback UI를 넣고 싶을 때 사용합니다.

Fallback, FallbackRender, FallbackComponent 셋중 하나는 반드시 있어야 합니다!

  • onError
    ErrorBoundary 내에서 Error가 발생하였을 때 실행됩니다.
    'error', 'info'를 argument로 가집니다.

useErrorHandler

  • React에서 Error Boundary는 다음과 같은 에러는 포착하지 않습니다.

    1. 이벤트 핸들러에서의 에러
    2. 비동기적 코드에서의 에러
    3. 서버사이드 렌더링에서의 에러
    4. 자식에서가 아닌, 에러 경계 자체에서 발생하는 에러

따라서 react-error-boundary에서는 위의 경우에 발생하는 에러를 핸들링하기 위해 useErrorHandler를 제공합니다.

  • 사용방법
    1. const handleError = useErrorHandler() 선언
    2. useErrorHandler(error) 으로 사용

0개의 댓글