개발자

invalidateQueries를 사용했을 때, UI가 Re-Render 되지 않습니다.

2023년 04월 12일조회 1,543

안녕하세요, 현재 useQuery를 사용해서 인증과 동시에 유저 데이터를 가져오고 있고, 이 유저 데이터 중 닉네임을 변경하는 코드를 만들고 있어요. 제가 원하는 동작은 닉네임을 변경했을 때, 변경된 닉네임으로 Re-Render 되어서 화면에 보여지는 거예요. 문제는 invalidateQueries를 사용해서 캐시를 무효화해도, 변경된 닉네임으로 화면이 바뀌질 않아요. React-Query DevTools에선 캐시 데이터가 변경된 것을 확인했고, useMutation 훅을 사용해서 닉네임을 변경해봐도 결과는 같았습니다. 이상하게도, 사이트의 네비게이션 바의 프로필 UI에선 닉네임이 즉시 변경되었는데요, 이 네비게이션 바 외에선 자동으로 Re-Render 되지 않습니다. 이와 관련해서 아시는 분이 계실까요?

이 질문이 도움이 되었나요?
'추천해요' 버튼을 누르면 좋은 질문이 더 많은 사람에게 노출될 수 있어요. '보충이 필요해요' 버튼을 누르면 질문자에게 질문 내용 보충을 요청하는 알림이 가요.
profile picture
익명님의 질문

답변 4

김진건님의 프로필 사진

refetchQueries 한번 사용해보세요!

profile picture

익명

작성자

2023년 04월 13일

결과가 동일하네요ㅜ

김현진님의 프로필 사진

useQuery에 fetcher를 비동기적으로 사용하는 것이 어떨까 싶습니다. useAuth의 useQuery에서 fetcher의 동작과 select의 동작 사이에서 싱크가 맞지 않아 낡은 데이터를 그대로 사용하는 것 같습니다.

1
2
3
4
5
6
7
export function useAuth() {
  const fetcher = async () => {
    const response = await request.get('/api/auth');
    return response.data;
  };
  return useQuery(queryKeys.AUTH_USER, fetcher);
}
profile picture

익명

작성자

2023년 04월 13일

말씀해주신 대로 변경해보았으나 결과는 같았네요ㅜ 콘솔로 디버깅 해보니 ProfileUpdateTest 컴포넌트에서의 useAuth()가 refetch를 하지 않고 있는 것으로 확인됐는데 이유를 모르겠네요..

김현진님의 프로필 사진

김현진

퍼블리 소프트웨어엔지니어2023년 04월 13일

그렇다면 test 함수가 문제인거 같네요 api가 호출되고 난 이후에 invalidateQueries가 제대로 실행이 안 된거 같습니다. invalidateQueries에 return이 있으면 해당 state가 update 될때까지 loading state가 유지된다고 합니다 function test() { axios.put('/api/user/nickname', { user_id: 3, nickname: inputRef.current?.value }).then(() => { return queryClient.invalidateQueries(queryKeys.AUTH_USER); }); }

profile picture

익명

작성자

2023년 04월 13일

invalidateQueries를 반환해도 동일하네요ㅜ 원글의 소스 코드를 현재 코드로 수정했습니다. useMutation 구조로 다시 변경해보니 컴포넌트가 리렌더는 됐습니다만 useAuth에서 refetch는 하지 않는 모습입니다..

김현진님의 프로필 사진

김현진

퍼블리 소프트웨어엔지니어2023년 04월 13일

꼭 해결 됏으면 좋겠네요 혹시 useAuth('topnav'); 코드를 호출하는 네비게이션 바 코드도 올려주실 수 있을까요?

profile picture

익명

작성자

2023년 04월 13일

넵 감사합니다. useAuth 함수 밑에 ProfileDropdown 코드를 추가했습니다.

profile picture

익명

작성자

2023년 04월 13일

에고.. 문제가 뭔지 알아냈네요. App 컴포넌트에서 queryClient를 생성하고 이를 프로바이더로 전달해주고 있었는데요, 앱이 리렌더링 될 때마다 queryClient가 새로 생성되는 것이 문제였던 것 같습니다. 코드를 아래와 같이 수정했습니다. 수정 전 cosnt queryClient = new QueryClient(); 수정 후 const [queryClient] = useState(() => new QueryClient()); 참고 문서 https://tkdodo.eu/blog/react-query-fa-qs#2-the-queryclient-is-not-stable 바쁘실 텐데도 귀한 시간 내주시며 도와주셔서 감사합니다! 답변해주신 것 덕분에 생각이 정리가 되었는지 답을 찾는 데 큰 도움이 되었습니다.

김현진님의 프로필 사진

김현진

퍼블리 소프트웨어엔지니어2023년 04월 13일

안그래도 cosnt queryClient 쪽에 영향이 있을까 확인해보고 있었습니다ㅎㅎ 해결되었다니 다행이에요 useMutation도 훅으로 분리하고 그 안에서 cosnt queryClient를 생성하면 깔끔할거 같습니다. function useUserUpdate() { cosnt queryClient = new QueryClient(); const { mutate } = useMutation(fetcher, { onSuccess: () => { return queryClient.invalidateQueries(queryKeys.AUTH_USER); }, }); return { mutate }; }

profile picture

익명

작성자

2023년 04월 13일

넵 따로 훅으로 만드는 게 깔끔하겠네요! 예시 코드도 감사드립니다.

종현님의 프로필 사진

안녕하세요! 저도 mutate를 통해서 수정을 했을때, 변경된 데이터로 동기화가 되지않아서 며칠동안 해결 못했던 경험이 있는데 같은 방법으로 해결이 되실수 있을까 하고 답변 남깁니다! queryClient.invalidateQueries에 refetchType이라는 옵션을 사용해서 refetchType: 'all', 옵션을 추가하는 방식으로 사용해보시겠어요?? 옵션으로는 4가지 선택지가 있네요! 상황에 맞춰서 적용해보시면 될것 같아요. 혹시 몰라 공식문서 링크와 해당설명부 첨부하겠습니다! https://tanstack.com/query/v4/docs/react/reference/QueryClient#queryclientinvalidatequeries refetchType?: 'active' | 'inactive' | 'all' | 'none' Defaults to 'active' When set to active, only queries that match the refetch predicate and are actively being rendered via useQuery and friends will be refetched in the background. When set to inactive, only queries that match the refetch predicate and are NOT actively being rendered via useQuery and friends will be refetched in the background. When set to all, all queries that match the refetch predicate will be refetched in the background. When set to none, no queries will be refetched, and those that match the refetch predicate will be marked as invalid only.

profile picture

익명

작성자

2023년 04월 13일

제 경우엔 queryClient 생성하는 부분에서 문제가 발생했었네요ㅜ 말씀해주신 refetchType 옵션도 한번 자세히 살펴보겠습니다. 답변 감사합니다!

종현님의 프로필 사진

종현

프론트엔드 개발자2023년 04월 13일

해결되었다니 다행이네요! 좋은하루 보내세요~~

커리어리 AI 봇님의 프로필 사진

React Query에서 캐시 무효화 및 리렌더링이 잘 되지 않는 문제는 종종 의존성 업데이트나 캐시 키 관련 문제로 발생할 수 있습니다. 다음 방법을 시도하여 문제를 해결해 보세요. 1. 캐시 키 확인: ' queryKeys.AUTH_USER '를 사용해 쿼리를 무효화했는데도 리렌더링이 발생하지 않는다면, 캐시 키가 일치하지 않는 것일 수 있습니다. 캐시 키가 모든 관련 쿼리에서 동일한지 확인하세요. 2. 의존성 확인: ' useAuth '의 의존성에 관련된 문제일 수도 있습니다. ' useEffect '를 사용하여 의존성을 처리하거나, 필요한 경우 ' useCallback '으로 감싸서 렌더링 사이에 함수를 동일하게 유지할 수 있습니다. 3. React Query Devtools 확인: 문제가 발생하는 페이지에서 React Query Devtools를 사용하여 캐시 상태와 관련된 정보를 확인하세요. 올바른 캐시 키와 함께 쿼리가 무효화되고 있는지 확인할 수 있습니다. 4. 직접 데이터 갱신: ' useMutation '의 ' onSuccess ' 콜백에서 ' queryClient.invalidateQueries() '를 사용하는 대신, ' queryClient.setQueryData() '를 사용하여 캐시에 있는 데이터를 직접 갱신할 수 있습니다. 이렇게 하면 리렌더링이 강제로 발생하게 됩니다. 위의 방법 중 하나를 사용하여 문제를 해결해 보세요. 그래도 문제가 해결되지 않는다면, 추가적인 디버깅이 필요할 수 있습니다.

1
2
3
4
5
6
#4
const { mutate } = useMutation(fetcher, {
  onSuccess: (newData) => {
    queryClient.setQueryData(queryKeys.AUTH_USER, newData);
  },
});

커리어리 AI 봇의 답변을 평가해 주세요!

지금 가입하면 모든 질문의 답변을 볼 수 있어요!

현직자들의 명쾌한 답변을 얻을 수 있어요.

또는

이미 회원이신가요?

목록으로
키워드로 질문 모아보기

실무, 커리어 고민이 있다면

새로운 질문 올리기

지금 가입하면 모든 질문의 답변을 볼 수 있어요!