react로 스터디하고 있는 앱을 만들고 있었는데, 에러처리를 뭔가 공통화하고 싶어서 검색하다가 errorboundary 에 대해 알게 되었다.
사용방법
생명주기 메서드인 static getDerivedStateFromError()
와 componentDidCatch() 중 하나 (혹은 둘 다)를 정의하면 클래스 컴포넌트 자체가 에러 경계가 된다. 에러가 발생한 뒤에 폴백 UI를 렌더링하려면 static getDerivedStateFromError()를 사용하고, 에러 정보를 기록하려면 componentDidCatch() 를 사용한다.
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;
}
}
<ErrorBoundary>
<ExampleComponenet />
</ErrorBoundary>
주의할 점
다음과 같은 에러는 처리하지 않는다.
(1) 이벤트 핸들러
(2) 비동기적 코드 (예: setTimeout 혹은 requestAnimationFrame 콜백)
(3) 서버 사이드 렌더링
(4) 자식에서가 아닌 에러 경계 자체에서 발생하는 에러
내가 사실 만든 앱에서 해야할 것은, 비동기적 에러처리가 중요했다. 그런데 비동기적 에러처리를 하지 않는다니.. 그래서 찾아본 결과,
unhandledrejection 이벤트를 사용하면 된다고 했다.
사용방법
import { useEffect } from "react";
export default function ErrorBoundary({ children }) {
const captureReject = (e) => {
e.preventDefault();
if (e.reason instanceof Error) {
window.alert(e.reason.message); //reason 에 에러 인스턴스가 담긴다.
return;
}
};
useEffect(() => {
window.addEventListener('unhandledrejection', captureReject);
return () => {
window.removeEventListener('unhandledrejection', captureReject);
}
}, []);
return children;
}
<ErrorBoundary>
<ExampleComponenet />
</ErrorBoundary>
cc. https://ko.reactjs.org/docs/error-boundaries.html#how-about-event-handlers , https://velog.io/@seo__namu/React-Error-Boundary로-비동기-에러-잡아내기