[refactor] useQuery 사용할 때 주의할 점

KoEunseo·2023년 5월 28일
0

project

목록 보기
35/37
post-thumbnail
post-custom-banner

1. 발단

유저네임 앞에 아이콘이 하나 있다. 이것은 유저가 기분을 선택했을 때, 그 기분의 색을 나타내준다. 하나의 귀여운 포인트랄까. 그런데 이게 작동하지 않는 것을 발견했다.

2. 어떤 부분이 문제였나

최대한 영어를 배제하고 한글로 서비스를 하고 싶었던 우리...^_^
그래서 display는 한글로 되도록 하고 있다.
무드카드를 보면 '행복' 이런식으로 한글로 나타나 있는 것을 볼 수 있다.
그러나 팔레트는 영어로 되어있다.
userMood === palette.mood 를 리턴하도록 했으니 아무것도 나오지 않을 수밖에 없었다.

3. 고치자

그래서 열심히 고민해서 고쳐봤다.
기존에는 유저의 팔레트를 useQuery로 받아오고, redux로 유저의 오늘 기분을 받아와 비교했었다.
비동기 데이터에서 리덕스를 최대한 배제하고 싶어서 어떻게 고치면 될까 고민하다가 api 문서를 살펴봤다.
유저 디스플레이네임을 안다면 유저의 오늘 기분을 가져올 수 있다! mood/day/${displayName} 을 사용하면 됐다.

이미 한차례 리팩토링을 통해 유저인포를 useQuery로 받아오고 있다.
그렇다면 유저인포에서 디스플레이네임을 가져와서 바로 사용하면 되겠구나!

근데 유저인포는 isLoading, isError와 함께 사용하고있었다.
별생각없이 isLoading과 isError를 지나 컴포넌트 return 하기 직전에 dayMood 쿼리를 썼다.

4. 또 에러

머지하고 로그인했더니 런타임에러가 났다. 리액트에서 이런 에러가 난다.

Rendered more hooks than during the previous render.

키워드를 찾아보니 useState를 최상단에서 쓰지 않거나 조건문에서 사용하면 나는 에러라고 한다.
그렇다면 useQuery도 마찬가지의 이유로 에러가 난 것 같다는 생각이 들었다.

5. enabled: !!userInfo,

위 코드를 쿼리에 추가해 userInfo가 존재할 때만 쿼리가 실행되도록 수정했다.

6. 해결! 인줄 알았는데...

7. 새로고침하면 색을 읽는 그대

대체 왜그러는데??? 👾

리액트쿼리는 쿼리 결과를 자동으로 캐싱해 재사용한다. 컴포넌트가 마운트되었을때만 쿼리를 실행하고, 그 후에는 캐시된 데이터를 반환한다. 새로고침하면 컴포넌트가 다시 마운트되고, 이전에 캐시된 데이터가 초기화된다.
dayMood 쿼리의 경우에는 userInfo가 존재할 때에만 쿼리를 실행하도록 했다. userInfo는 새로고침 시에 초기화된다. 초기화되면 undefined이기 때문에 enabled는 'false' 값을 가지게 되어 실행되지 않는 것...

8. 쿼리 키에 userInfo를 추가해서 해결

  const dayMood = useQuery({
    queryKey: ['dayMood', userInfo?.displayName],
    queryFn: async () => {
      const data = await getDayMood(userInfo?.displayName);
      return data;
    },
    enabled: !!userInfo,
  });

쿼리 키에도 userInfo.displayName을 포함시켰다. userInfo가 변경되면 dayMood 쿼리도 실행될것이다.

9. 이 될 줄 알았으나 안됐다...

진짜 희안한게

처음 로그인하면 이렇게 잘만 나온다.
근데 새로고침을 한번 하면

??? 왜 모달에 100%준건 사라지는걸까??? 🤔

리액트쿼리가 아니라 기존의 리덕스를 사용하면 해결이 될 것 같다. 그치만 비동기 데이터를 리덕스로 관리하는것은 점짐적으로 줄이고 싶다...
무드컬러가 바뀔때마다 userName 영역에서 컬러를 추적하게 하고 싶으면 무드카드 컴포넌트를 만져야 하는데, 다른 팀원분의 코드라서 간단한 것도 아니고 로직을 바꾸는 게 좀...
내일이 면접이라 문제를 해결하고 싶지만 이만 하고 내일모래 팀원분들께 개인적으로 연락을 좀 하고 계속해서 리팩토링을 진행해봐야겠다.

10. 된다...

코드를 더 바꾸지 않았는데 제대로 작동이 된다.
새로고침해도 제대로 작동이 됨!! ㅎㅎ
아마 코드는 바뀌었지만 리렌더링 될때는 기존의 페이지 구성 요소가 캐시되어있었기 때문에 빠져서 페인팅되었기 때문인 것 같다.

profile
주니어 플러터 개발자의 고군분투기
post-custom-banner

0개의 댓글