프로그래밍/React

비동기 호출과 ErrorBoundarry에 대해

콘파냐 2021. 12. 16. 18:39

우리는 종종 비동기 api호출을 useEffect 내에서 할 경우가 있다.
이 때 async ~ await을 사용한다 가정한다.
에초에 useEffect에 전달되는 첫 번째 파라미터 함수는 동기함수며 동기 함수 내에서 비동기 호출을 처리를 하기 위해서는 호출할 비동기함수를 또 다른 비동기 함수로 감싸줘야 한다.

async function fetchData() {
    ...
}
useEffect(()=> {

const func = async ()=> {
    const response = await fetchData();
}
func();
},[])

그리고 위 코드 처럼 결국엔 func 함수가 비동기적으로 호출되기 때문에 호출 결과를 동기적으로 처리할 수 없다.
따라서 fetchData의 결과로 Error가 발생된다 하더라도 이미 useEffect의 콜백 함수는 실행이 끝난 후이며 컴포넌트 렌더링까지 마쳤을 지도 모른다. 이렇게 비동기적으로 처리되는 함수의 에러에 대해서는 ErrorBoudndary 로 에러가 전파되지 않는다는 문제가 있다.
일반적인 언어들의 비동기 처리를 생각한다면 이해가 된다.
그래서 자료를 찾아보니 다음과 같은 내용을 발견할 수 있었다.
참고
Note

Error boundaries do not catch errors for:

Event handlers (learn more)
Asynchronous code (e.g. setTimeout or requestAnimationFrame callbacks)
Server side rendering
Errors thrown in the error boundary itself (rather than its children)

또한 스택 오버플로에서 적절할 해결 방법을 찾을 수 있었음.
해결

function MyComponent() {
  const [error, setError] = useState(null);
  if (error) {
    throw error;
  }

  useEffect(() => {
    // If loading fails, save the error in state so the component throws when it rerenders
    load().catch(err => setError(err));
  }, []);

  return <div>...</div>
}

적절하게 응용하면 된다.
에러 핸들링의 핵심은 호출할 비동기 함수에서 발생되는 에러와 메인 컴포넌트 컨택스트를 state를 통해서 연결해준 것이라고 이해하면 된다. 비동기 호출 흐름에서 에러 발생 -> 메인 컴포넌트의 error 상태 변경 -> 에러 상태의 변경으로 새롭게 컴포넌트 렌더링 중 throw error 실행 -> ErrorBoundary 에서 에러 잡아냄.
이 해결책이 나쁘지 않아보인다.

반응형