type ErrorHandlingComponent<Props> = (props: Props, error?: Error) => ReactNode;

type ErrorState = { error?: Error };

function Catch<Props extends {}>(component: ErrorHandlingComponent<Props>): ComponentType<Props> {
  return class extends Component<Props, ErrorState> {
    state: ErrorState = {
      error: undefined,
    };

    static getDerivedStateFromError(error: Error) {
      return { error };
    }

    render() {
      return component(this.props, this.state.error);
    }
  };
}

type Props = {
  children: ReactNode;
};

export const ErrorBoundary = Catch(function ErrorBoundary(props: Props, error?: Error | CommonError) {
  if (error !== undefined) {
    return (
	      ...
    );
  }

  return <>{props.children}</>;
});

getDerivedStateFromError

  1. **getDerivedStateFromError**는 오류 처리에만 사용되어야 합니다. 즉, 이 메서드 내에서 새로운 상태를 반환하여 컴포넌트의 상태를 업데이트하는 것이 목적입니다.
  2. 이 메서드가 호출되면 해당 컴포넌트와 그 자식 컴포넌트의 렌더링이 멈춥니다. 오류 처리 후에 컴포넌트의 상태가 업데이트되어 다시 렌더링되어야 합니다.
  3. 오류 처리 후에 컴포넌트의 render 메서드가 호출되므로, **getDerivedStateFromError**에서 반환한 새로운 상태를 이용하여 UI를 업데이트할 수 있습니다.

Catch(고차함수임)에 ErrorHandlingComponent라는 컴포넌트를 인자로 넘겨준다

만약 에러가 발생하면 **getDerivedStateFromError**가 에러를 잡아서 반환하고 render에서 잡은 에러를 props로 넘겨준다.

이때 넘긴 props는 ErrorHandlingComponent에게 넘어가게 되고 이는 Catch(여기) 에 넣은 컴포넌트에게 넘어가는 것이기 때문에 이 컴포넌트 내부에서 분기해서 에러에 대한 화면을 그려준다면 선언적으로 에러 핸들링을 할 수 있음!