본문 바로가기
React/ReactNative

[ReactNative] react-query refetch가 안되는 문제와 해결 방법

by lumayi 2024. 3. 6.

문제 상황

리액트 쿼리는 기본적으로 화면이 focus될 경우, refetch되는 속성을 가지고 있다.

그래서 화면을 이탈했다 돌아오면, stale시간과 상관없이 다시 새로운 데이터로 fetching 되게 된다.

 

하지만 리액트 네이티브에선 화면의 focusing 여부를 알지 못했다.

그래서 아무리 다른 페이지에 갔다 돌아와도, 데이터가 변경이 되어도, 리액트 쿼리는 계속해서 이전의 데이터만을 보여주게 된다.

 

이를 어떻게 해결할 수 있을까?

 

해결 방법

직접 custom hook을 구현하는 것으로 해결할 수 있다!

스크린이 focus 될 때마다, react query의 refetch 함수를 실행시키는 훅을 만들 수 있다.

커스텀 훅에 원하는 refetch 함수를 파라미터로 넘겨주도록 만들어주면 된다.

import {useFocusEffect} from '@react-navigation/native';
import React, {useCallback, useEffect, useState} from 'react';

export const useRefetchOnFocus = (refetch = () => {}) => {
  const [isScreenFocused, setIsScreenFocused] = useState(false);
  
  // useFocusEffect 사용시 주의 사항!! 본문 참고!!
  useFocusEffect(
    useCallback(() => {
      setIsScreenFocused(true);
      return () => setIsScreenFocused(false);
    }, []),
  );

  const fetchAgain = useCallback(() => {
    refetch();
  }, [refetch]);

  useEffect(() => {
    if (isScreenFocused) {
      fetchAgain();
    }
  }, [isScreenFocused, fetchAgain]);
};

 

이렇게[useRefetchOnFocus 라는 커스텀 훅을 만들어 주었다.

useFocusEffect는 스크린이 Focus되었을 때, 동작하는 hook인데, useFocusEffect안에 그냥 바로 refetch 함수를 호출해버리면 되지않나 싶은 생각이 들 수 있다.

 

하지만 useFocusEffect를 사용할 땐 주의 사항이 있다.

[1] 전달되는 callback은 꼭 useCallback으로 감싸져야 한다는 것이다.

그렇지 않으면 너무 잦은 함수의 호출과 렌더링이 일어나게 되므로 성능 저하가 발생하게 된다. 또한 함수를 리턴해주는 것도 잊지말자.

 

그리고 [2] refetch 함수가 변경되었을 때도, 새롭게 호출되게 하기위해 위의 코드와 같이 useFocusEffect에서는 상태만을 변경시키고, 그로 인해 상태가 변경될 경우, 조건을 추가하여 fetchAgain이 호출되도록 했다.

 

사용하는 곳은 아래와 같다!

const {data: friendFundingsQuery, refetch: refetchFriendFudingQuery} =
    useQuery({
      queryKey: ['friendsFunds', user?.id],
      select: data => data.content,
      queryFn: () => funding.findFriendFundings(statuses, page, size, sort),
    });

// 호출부
useRefetchOnFocus(refetchFriendFudingQuery);

 

 

이렇게 다른 페이지 이동했다가 돌아올 시에 데이터가 잘 fetching 된 것을 알 수 있다! 

반응형