이전 두번의 팀 프로젝트에서 React query 를 사용했었다. 하지만 부족한 이해도로 인해
'이게 되네?'
또는'이게 왜 안돼?'
하는 상황이 종종 있었다.
이 친구를 다시 사용하게 될 미래를 위해, 제대로 사용하기 위한 개념과 사용 패턴들을 차근차근 정리해보고자 한다 !
loading
, error
, pending
…)를 핸들링하기 위한 로직을 구현 했어야 함 ⇒ 예를 들면 try-catch
number | Infinity
default = 0
number | Infinity
default = 5분
1️⃣ 해당 페이지 진입, 브라우저 재포커싱 ⇒ 컴포넌트 mount
2️⃣ 쿼리 인스턴스 mount (pending
)
3️⃣ staleTime 이 지났는가? (stale 한 데이터인가?)
fetching
)loading
)이걸 도식화해보면 아래와 같다!
😳 그동안 잘 모르고 사용했거나, 헷갈리는 부분 정리
staleTime 의 default 값은 0 이기 때문에, 기본적으로 캐시 기능을 사용하고 있지 않다고 보면 된다. 쿼리 인스턴스가 mount가 되면, 무조건 데이터 업데이트가 일어나기 때문이다.
그렇다면 staleTime 이 0 일때 캐시의 역할은, 데이터를 업데이트할 때 빈화면이나 로딩화면이 아닌 이전 데이터를 보여주기 위함이다.
isLoading은 캐싱된 데이터가 없을 때, 즉 초기 데이터일 때만 true
이다. 따라서 isLoading 을 무조건적인 로딩UI의 trigger로 쓰는 것은 좋지 않다.
쿼리 인스턴스가 반환하는 refetch 함수를 호출하게 될 경우, stale/fresh에 관계 없이 데이터 업데이트가 이루어진다. 따라서 이 함수에 의존하는 것은 리액트 쿼리 기능에 위배된다.
캐시된 데이터에 무관하게 즉시 업데이트를 원한다면, invalidateQuery 를 통해 해당 쿼리의 캐시를 초기화시켜야 한다.
staleTime > gcTime
?staleTime 이 지나지 않으면 데이터 패칭을 하지 않으며, 그렇게 되면 캐시도 쳐다보지 않기 때문에 캐싱이 의미가 없음
그렇다면 무조건
staleTime < gcTime
?자주 사용하지 않는 데이터의 경우, staleTime 을 길게 설정할 수 있다. 이러한 경우 gcTime 을 굳이 더 길게 잡으면 메모리를 낭비하게 된다.
staleTime vs cacheTime · TanStack/query · Discussion #1685
실시간 처리, 특정 주기를 가지고 서버와 응답을 주고 받는 방식
refetchInterval
특정 시간마다 자동으로 refetch
refetchIntervalInBackground
브라우저 탭/창이 백그라운드에 있는 동안에도 (focus 되지 않아도) refetch
refetchOnWindowFocus
브라우저 탭/창이 focus 될 때 refetch
1. refetchInterval In Background
const { data, ... } = useQuery({
...queryOption,
refetchInterval: 2000,
refetchIntervalInBackground: true,
});
2. refetch On Window Focus
const { data, ... } = useQuery({
...queryOption,
refetchInterval: 2000,
refetchOnWindowFocus: true
});
쿼리가 pending
인 동안 해당 쿼리의 데이터로 반환됨
placeholderData = 서버 데이터랑 관련 없는, 보여주기용 가짜 데이터
캐시에 유지되지 않음 (initialData 와의 차이점)
pending = 쿼리 인스턴스에 데이터가 없는 상태
1. 단순 값을 placeholderData 에 할당하기
const result = useQuery({
queryKey: ['todos'],
queryFn: () => fetch('/todos'),
placeholderData: placeholderTodos,
})
2. 함수를 placeholderData 에 할당하기
함수 : (이전 쿼리 데이터, 이전 쿼리 인스턴스) => 이전 쿼리 데이터
하나의 쿼리([’todos’, 1]
)에서 가져온 데이터를 다른 쿼리([’todos’, 2]
)의 데이터로 사용
pagination 기능을 구현할 때 사용
const result = useQuery({
queryKey: ['todos', id],
queryFn: () => fetch(`/todos/${id}`),
placeholderData: (previousData, previousQuery) => previousData,
})
import { keepPreviousData, ... } from '@tanstack/react-query'
const result = useQuery({
queryKey: ['todos', id],
queryFn: () => fetch(`/todos/${id}`),
placeholderData: keepPreviousData
})
쿼리 초기 데이터를 캐시에 제공
isLoading = 캐시에 데이터가 없어서 API 요청을 새로 하는 상태
iniaitlData 는 기본적으로 fresh 데이터로 처리되기 때문에, staleTime 로직에 영향을 줌
1. 전체 데이터를 상세 데이터 초기값에 할당하기
전체 리스트 페이지에서 상세 페이지로 접속할 때,
같은 데이터를 사용함에도 똑같이 쿼리 작업이 수행되는 부분을 해결하기 위함
상세 페이지에서는 쿼리 작업을 하지 않고 앞에서 구한 데이터를 가져와서 쓰기
⇒ 네트워크 사용량 감소
const result = useQuery({
queryKey: ['todo', todoId],
queryFn: () => fetch(`/todos/${todoId}`),
initialData: () =>
queryClient.getQueryData(['todos'])?
.find((d) => d.id === todoId),
})
글이 너무 길어져서, 다시 돌아오겠숩니다..!
정리한 지식 호로록 흡수할게요