얼마 전 왜 ErrorBoundary는 비동기 코드에서 발생하는 에러를 캐치하지 못하는지 의문이 생겨 동작 방식을 살펴보았다.
React는 자신이 직접 실행하는 렌더링과 생명주기 처리 중 에러를 포착하고, 컴포넌트 트리의 부모 관계를 따라 가장 가까운 ErrorBoundary에 전달한다.
반면 API 요청의 Promise 콜백은 React의 렌더링 과정 밖에서 실행되므로, 콜백에서 발생한 에러는 ErrorBoundary에 전달되지 않는다.
그럼에도 풀리지 않는 의문은, 분명히 다른 아티클에서는
API 호출에서 발생한 에러를 ErrorBoundary가 처리하도록 하는 것을 봤다는 것이다.
아래처럼 비동기 에러를 state에 저장한 뒤 렌더링 중 다시 throw하면
ErrorBoundary가 감지할 수 있다.
const [error, setError] = useState();
useEffect(() => {
const fetchTodos = async () => {
try {
await getTodos();
} catch (e) {
setError(e);
}
};
fetchTodos();
}, []);
if (error) {
throw error;
}
위 코드가 App 컴포넌트 내부 코드라고 가정하고
App 컴포넌트는 ErrorBoundary에 의해 감싸져있고
App 컴포넌트 내부의 getTodos api 함수에서 에러가 발생했다고 하자.
이런 순차적인 단계를 통해서 비동기 컨텍스트에서 발생한 에러를
렌더링 중 다시 throw하여 ErrorBoundary가 감지할 수 있게 하는 것이다.
이번 계기를 통해 React가 렌더링 과정에서 발생한 에러를 컴포넌트 트리를 따라 ErrorBoundary에 전달한다는 것을 알게 되었다.
앞으로도 React의 기능을 사용법만 외우기보다 실제 동작 범위를 이해하며 사용하도록 노력해야겠다.