오류해결

[react-query] 네트워크 요청은 한 번 콜백함수는 두 번 실행이 되는문제

Summer.dev 2023. 8. 29. 01:35

지난번 리팩토링 글에서

서버에서 받아온 데이터를 redux로 관리하는 대신 react-query의 캐싱기능으로 상태관리를 해주었는데요

여기서 redux의 useSelector처럼 useQuery를 커스텀 훅으로 만들어 return 값을 사용했습니다.

  const { myData, isLoading, error } = useMyInfo();

두 번 실행되는 콜백함수

해당 커스텀 훅은 유저의 정보를 리턴합니다.

모모의 홈페이지에 들어갔을때

1. 유저의 프로필사진과 닉네임이 필요한 <Header> 컴포넌트

2. 유저의 지역 정보가 필요한 <ListsHeader> 컴포넌트

이렇게 두 개의 컴포넌트에서 커스텀 훅이 실행이 됩니다.

 

저는 커스텀 훅을 여러번 호출이 되어도

캐싱된 데이터가 있으면 네트워크 요청이 한번만 가므로

콜백함수가 한번만 실행이 될 것이라고 생각했습니다.

 

하지만 실제로는

토큰이 만료되었을 때 커스텀 훅의 `onError` 콜백함수가 두 번 실행이 되어

토큰이 만료되었다는 alret창을 두 번 꺼야만 정상적인 로그아웃이 되었습니다.

네트워크 요청은 한 번가는데?

저는 네트워크 탭에서 한 번의 요청만 가는 것을 확인할 수 있었습니다.

그런데 콜백함수는 왜 두번 실행이 되었을까요?

 

https://github.com/TanStack/query/issues/1969

 

onSuccess callback in useQuery fires twice · Issue #1969 · TanStack/query

Describe the bug useQuery call one by one for same endpoint but for different components (one component should be child for other and parent should render child only on isLoading === false); To Rep...

github.com

위 문서에 따르면
1. 데이터가 fetch 되면
2. 같은 queryKey를 Observer에게 알림이 가며
3. 모든 onSuccess 등의 콜백함수가 새로운 데이터가 있기 때문에 trigger 된다고 설명하고 있습니다.

제 상황과 100% 일치 하는 질문은 아니었지만

위 부분에서 에러에 대한 해답을 찾았습니다.

 

해결방법

공식문서에서 on~ 콜백함수는 다음 버전에서 제거될 예정이며 권장하지 않는다는 내용이 있어

커스텀 훅의 onError 콜백함수가 아닌 리턴된 데이터로 에러처리를 하여 실패했을 때를 처리해 주었습니다.

 

기존 커스텀 훅의 onError 콜백함수는 삭제하고

어느 페이지에서나 존재하는 <Header> 컴포넌트에만 error 처리를 하여

토큰이 만료되었을때 두 번째 if문이 실행되어 콜백함수가 두번 호출 되는 에러를 해결하였습니다.

  const { myData, error } = useMyInfo();

  if (error) {
    console.log(error);
    if (error.response?.status === 401 && token) {
      navigate('/');
      localStorage.clear();
      queryClient.clear();
      alert('토큰이 만료되었습니다. 다시 로그인해주세요.');
    } else {
      console.error('오류가 발생했습니다.', error.message);
    }
  }