Tanstack Query 상태와 isLoading/isFetching/isPending

foresec·2024년 6월 5일

Project

목록 보기
7/11

계속 상태상태 하는데 isLoading/isFetching/isPending에 무슨 차이가 있지.. 하는 의문하며, 이참에 Tanstack Query의 Status에 대한 학습을 하고 가는게 좋겠다는 생각을 했다

Tanstack Query의 구조

status 이야기와 직접적으로 연결된건 아니지만...찾아보다가 Tanstack Query가 어떻게 작동하는지에 대해 잘 정리된 글이 있어 가져와봤다

React Query 내부 클래스 구조 및 클래스 간의 상호작용을 통해 만들어지는 흐름

출처 : https://fe-developers.kakaoent.com/2023/230720-react-query/

  1. Query 상태에 변화가 발생
  2. Query와 연결된 QueryObserver에 자신의 상태가 변화했음을 알림
  3. QueryObserver는 자신과 연결된 Listener에 관찰하고 있는 Query의 상태변화가 발생했는지 판단 후 필요시 Listerner에 알림
  4. Listener는 업데이트된 Query의 상태를 참조, 자신을 새로 갱신

아무튼 본격적으로 상태를 알아보자면,

Tanstack-query의 상태

두개의 상태가 분리되어 있다

// queryClient-K0zFyarY.d.ts
type QueryStatus = 'pending' | 'error' | 'success';
type FetchStatus = 'fetching' | 'paused' | 'idle';

Status

주요 state이자 기본적인 쿼리의 data 여부를 나타내는 상태

  • pending: 쿼리가 아직 데이터를 가지고 있지 않은 초기 상태
  • error: 쿼리에서 오류가 발생한 상태
  • success: 쿼리가 성공적으로 데이터를 가져온 상태

fetchStatus

addtional한 state로, 쿼리 함수(queryFn)의 실행 여부를 나타내는 상태

  • fetching: 쿼리가 현재 데이터를 가져오는 중인 상태
  • paused: 쿼리가 데이터를 가져오려 했지만 일시 중지된 상태(네트워크 모드 관련)
  • idle: 쿼리가 현재 아무 작업도 하지 않는 상태

왜 두가지 상태가 필요한가?

공식문서 : Background refetches and stale-while-revalidate logic make all combinations for status and fetchStatus possible.

Background Refetches

쿼리 데이터가 오래되었을 때 백그라운드에서 데이터를 다시 가져오는 과정. 사용자가 화면을 보고 있는 동안 최신 데이터를 유지함.

Stale-While-Revalidate

오래된 데이터를 즉시 제공하고 백그라운드에서 새로운 데이터를 가져와 캐시를 업데이트하는 캐싱 전략.

예를 들어, 다음과 같이 분리되어 작동한다.

  • 성공 상태(status === 'success')의 쿼리는 보통 idle(fetchStatus) 상태에 있지만, 백그라운드에서 재요청이 발생하면 fetching(fetchStatus) 상태일 수도 있다.

  • data가 없는 상태로 마운트된 쿼리는 보통 pending(status)와 fetching (fetchStatus)상태에 있지만, 네트워크 연결이 없을 경우 paused(fetchStatus) 상태일 수도 있다.

즉, 쿼리가 실제로 data를 가져오지 않고도 pending상태에 있을 수 있음

isLoading? isFetching? isPending?

isPending

(현) isPending = (구) isLoading
쿼리가 아직 데이터를 가지고 있지 않은 초기 상태 여부 (status관련)

isFetching

쿼리가 현재 데이터를 가져오는 중인 상태 여부(fetchStatus관련)
staleTime 만료 or cacheTime 만료 or refetch와 같이 데이터 업데이트가 필요할 때

isLoading

(현) isLoading = isFetching && isPending = (구) isInitialLoading
isLoading은 캐시된 데이터 없이 요청중인, 즉 현재 처음으로 가져오는 경우에만 true를 반환한다.

간단한 예시 3가지

  const {
    data: searchResults,
    isLoading,
		isPending,
		isFetching,
    isError,
    error,
  } = useQuery({
    queryKey: ["search", searchVal],
    queryFn: () => handleSearch(searchVal),
    enabled: !!searchVal.trim()
  });
	
	console.log("-----------------")
	console.log("isPending :", isPending)
	console.log("isFetching :", isFetching)
	console.log("isLoading :", isLoading)
	console.log("-----------------")

1. 아무 변화 없이 처음 mount

ex) 아무것도 입력하지 않은 상태(enabled = false인 상태)에서 해당 값을 확인하면

isPending : true
isFetching : false
isLoading : false

enabled를 false로 설정했을 때 useQuery가 내부적으로 data가 없는것으로(데이터 가져오는 중)으로 판단하여
-> isPending을 true로 반환한다.

2. 새로운 값을 입력했을 때

ex) 검색창에 'ㄱ'을 입력했을때

isPending : true
isFetching : true
isLoading : true

isPending : false
isFetching : false
isLoading : false

데이터를 받아온다

3. 위에서 이어 다른 값을 입력했다가 다시 돌아왔을 때

ex) 검색창에 'ㄱ'을 입력해본 상태에서 'ㄱㄴ'을 입력하고 다시 'ㄱ'으로 돌아왔을때

먼저, ㄱㄴ을 입력했을 때

isPending : true
isFetching : true
isLoading : true

isPending : false
isFetching : false
isLoading : false

그다음, ㄱ을 입력했을 때

isPending : false
isFetching : true
isLoading : false

isPending : false
isFetching : false
isLoading : false

isFetchng이 true인 이유는 staleTime이 0으로 설정(기본값)되어 있기 때문에 계속 fetching이 일어나기 때문이다. staleTime값을 임의로 지정해서 바꿔주면 false가 반환된다

하지만 isPending은 cacheTime이 5분으로 설정(기본값)되어 있는, 즉 캐싱된 상태이므로 false를, isLoading도 따라서 false를 반환한다

+isLoading이 아무래도 단어가 익숙해서 일단 썼는데 pending이랑 구분할 필요가 있다


https://highjoon-dev.vercel.app/blogs/4-status-checks-in-react-query

https://highjoon-dev.vercel.app/blogs/13-offline-react-query

https://velog.io/@rlwjd31/react-query-useQuery-isLoading-VS-isFetching

https://tanstack.com/query/latest/docs/framework/react/guides/queries#fetchstatus

https://yogjin.tistory.com/123

profile
왼쪽 태그보다 시리즈 위주로 구분

0개의 댓글