[React-Query] useQuery #01

곽재훈·2024년 6월 11일
post-thumbnail

useQuery

참조한 공식 문서

https://tanstack.com/query/latest/docs/framework/react/reference/useQuery


const {
  data,
  dataUpdatedAt,
  error,
  errorUpdatedAt,
  failureCount,
  failureReason,
  fetchStatus,
  isError,
  isFetched,
  isFetchedAfterMount,
  isFetching,
  isInitialLoading,
  isLoading,
  isLoadingError,
  isPaused,
  isPending,
  isPlaceholderData,
  isRefetchError,
  isRefetching,
  isStale,
  isSuccess,
  refetch,
  status,
} = useQuery(
  {
    queryKey,
    queryFn,
    gcTime,
    enabled,
    networkMode,
    initialData,
    initialDataUpdatedAt,
    meta,
    notifyOnChangeProps,
    placeholderData,
    queryKeyHashFn,
    refetchInterval,
    refetchIntervalInBackground,
    refetchOnMount,
    refetchOnReconnect,
    refetchOnWindowFocus,
    retry,
    retryOnMount,
    retryDelay,
    select,
    staleTime,
    structuralSharing,
    throwOnError,
  },
  queryClient,
)

오늘은 useQuery 에 대해서 공부할 예정!
useQuery에 인자로 전달하는 객체에 넣을 수 있는 옵션들과, useQuery가 반환하는 객체에서 사용할 수 있는 옵션들이 있는데 양이 되게 많아서 3-4일 정도로 나누어서 볼 예정!

useQuery에 넣을 수 있는 옵션들

1. queryKey

  • queryKey: unknown[]
    • Required
    • The query key to use for this query.
    • The query key will be hashed into a stable hash. See Query Keys for more information.
    • The query will automatically update when this key changes (as long as enabled is not set to false).

queryKey는 필수 옵션,

우리가 자료를 변수에 저장할 때, 변수를 식별하기 위해 변수명을 짓는 것처럼, 여러 쿼리들 사이에서 쿼리를 식별하고 관리하기 위해서 이름이 필요한 듯 하다.

그리고 queryKey: unknown[] 라는 부분을 보면 알 수 있듯이, queryKey의 값은 반드시 배열로 들어가야 한다. 예를 들면, queryKey: ["posts"] 이렇게 말이다.

이렇게 배열로 작성하는 이유는 쿼리들의 원활한 관리를 위해서인데,

예를 들어서 똑같이 posts 에 대한 데이터를 받아오더라도 어떤 데이터는 그 중에서 작성자 데이터만 모아왔을 수도 있고, 어떤 데이터는 날짜별로 정렬한 데이터를 받아왔을 수도 있는데 그 모든 걸 posts 라는 동일한 queryKey값으로 관리하려고 한다면 불편할 것이다.

const result = useQuery({
	queryKey : ["posts"],
	queryFn : ...
})

const result = useQuery({
	queryKey : ["posts", "sortedBy"],
	queryFn : ...
})

const result = useQuery({
	queryKey : ["posts", "authors"],
	queryFn : ...
})

이렇게 작성해놓으면 이 쿼리들이 모두 posts라는 queryKey를 공유하고 있기 때문에 원한다면 posts 라는 queryKey를 가진 모든 쿼리를 한 번에 조작할 수도 있고, 정확하게 "posts", "sortedBy" 라는 queryKey 를 가진 쿼리만 업데이트할 수도 있을 것이다.

enabled 옵션이 false 가 아니라면 queryKey 가 변경되었을 때 query가 자동으로 업데이트된다고 한다.

2. queryFn

  • queryFn: (context: QueryFunctionContext) => Promise<TData>
    • Required, but only if no default query function has been defined See Default Query Function for more information.
    • The function that the query will use to request data.
    • Receives a QueryFunctionContext
    • Must return a promise that will either resolve data or throw an error. The data cannot be undefined.

queryFn 도 필수 옵션인데, 만약 default query function 이 정의되어 있다면 필수적으로 적지 않아도 된다고 한다.

데이터를 요청하는데 사용할 이 queryFn 은 반드시 Promise 를 반환해야한다고 한다.

fetchaxios를 사용했더라도 함수가 Promise 를 반환하지 않는다면,

"error : The data cannot be undefined."

라는 에러를 만날 것이다.

3. enabled

  • enabled: boolean
    • Set this to false to disable this query from automatically running.
    • Can be used for Dependent Queries.

enabledfalse 로 설정하면 쿼리가 자동으로 업데이트되지 않는다는데, 이걸 언제 false 로 사용할까 라는 의문이 듦. 아직은 잘 모르겠음.

4. networkMode

  • networkMode: 'online' | 'always' | 'offlineFirst
    • optional
    • defaults to 'online'
    • see Network Mode for more information.

 Network Mode를 살펴보기.

defaultonline ,

Network Mode: always

In this mode, TanStack Query will always fetch and ignore the online / offline state. This is likely the mode you want to choose if you use TanStack Query in an environment where you don't need an active network connection for your Queries to work - e.g. if you just read from AsyncStorage, or if you just want to return Promise.resolve(5) from your queryFn.

  • Queries will never be paused because you have no network connection.
  • Retries will also not pause - your Query will go to error state if it fails.
  • refetchOnReconnect defaults to false in this mode, because reconnecting to the network is not a good indicator anymore that stale queries should be refetched. You can still turn it on if you want.

Promise.resolve(5) 처럼 Promise 를 반환하지만 네트워크 요청이 필요없는 경우나, AsyncStorage 를 읽는 요청 등의 경우에 사용한다고 되어 있는 걸 보니까 alwaysqueryFn 이 네트워크가 필요한 작업을 하지 않을 때 사용하는 느낌인가… 이건 정확히 모르겠다.

Network Mode: offlineFirst

This mode is the middle ground between the first two options, where TanStack Query will run the queryFn once, but then pause retries. This is very handy if you have a serviceWorker that intercepts a request for caching like in an offline-first PWA, or if you use HTTP caching via the Cache-Control header.

In those situations, the first fetch might succeed because it comes from an offline storage / cache. However, if there is a cache miss, the network request will go out and fail, in which case this mode behaves like an online query - pausing retries.

offlineFirst 의 경우, cache 와 관련된 것 같다.

5. retry

  • retry: boolean | number | (failureCount: number, error: TError) => boolean
    • If false, failed queries will not retry by default.
    • If true, failed queries will retry infinitely.
    • If set to a number, e.g. 3, failed queries will retry until the failed query count meets that number.
    • defaults to 3 on the client and 0 on the server

retry 옵션은 boolean 이나 number 을 값으로 받는다. true 면 성공할 때까지 재시도를 무한 반복하게 되고, false 일 경우 재시도를 하지 않는다. number 일 경우, 숫자에 적힌 만큼 재시도를 한다.

기본값은 클라이언트는 3, 서버는 0이다.

6. retryOnMount

  • retryOnMount: boolean
    • If set to false, the query will not be retried on mount if it contains an error. Defaults to true.

retryOnMountfalse 로 설정하면, 오류가 포함된 쿼리의 경우 마운트할 때 다시 시도하지 않는다고 적혀있다.

기본값은 true

7. retryDelay

  • retryDelay: number | (retryAttempt: number, error: TError) => number
    • This function receives a retryAttempt integer and the actual Error and returns the delay to apply before the next attempt in milliseconds.
    • A function like attempt => Math.min(attempt > 1 ? 2 ** attempt * 1000 : 1000, 30 * 1000) applies exponential backoff.
    • A function like attempt => attempt * 1000 applies linear backoff.

이 옵션은 retryDelay , 즉 요청이 실패했을 때 다음 재시도 요청까지의 지연 시간을 결정하는 옵션이다.

함수의 인자로 attempt 를 받아 거기에 millisecond를 곱해서 지연시간을 결정하는 게 일반적인 사용법인 것 같다.

재시도 지연의 경우, 내 기억이 맞다면 exponential backoff delay 방식이 default 로 설정되어 있다. 이는 네트워크 요청이 실패했을 경우, 연속적이고 빠른 재요청은 실패의 가능성이 높고 서버에 큰 부하를 줄 수 있기 때문에 지연 시간을 지수 곱의 형태로 늘려서 서버에 대한 부하를 줄이기 위함이라고 알고 있다.

8. staleTime

  • staleTime: number | Infinity
    • Optional
    • Defaults to 0
    • The time in milliseconds after data is considered stale. This value only applies to the hook it is defined on.
    • If set to Infinity, the data will never be considered stale

staleTimenumber 혹은 infinity 를 값으로 받을 수 있는데, infinity 로 설정할 경우 query의 데이터가 stale 상태로 바뀌지 않고 항상 fresh 상태로 유지된다.

query에서는 동일한 요청을 했을 때, 데이터가 stale 상태가 아니라 fresh 상태라면, 새로 서버에 데이터를 요청하는 것이 아니라 기존에 갖고 있던 cache 에서 데이터를 보여준다.

기본값은 0이기 때문에 새로운 요청을 할 경우, 언제나 서버에 데이터를 새로 요청한다.

9. gcTime

  • gcTime: number | Infinity
    • Defaults to 5 60 1000 (5 minutes) or Infinity during SSR
    • The time in milliseconds that unused/inactive cache data remains in memory. When a query's cache becomes unused or inactive, that cache data will be garbage collected after this duration. When different garbage collection times are specified, the longest one will be used.
    • Note: the maximum allowed time is about 24 days. See more.
    • If set to Infinity, will disable garbage collection

데이터가 stale 상태가 된 이후, garbage collection 에 수집되기까지 걸리는 시간을 정의하는 옵션이다. 기본값은 5분이고, 무한대로 설정하면 더이상 수거되지 않는다.

10. queryKeyHashFn

  • queryKeyHashFn: (queryKey: QueryKey) => string
    • Optional
    • If specified, this function is used to hash the queryKey to a string.

해시는 아직 잘 몰라서 패스…


내일 계속

profile
개발하고 싶은 국문과 머시기

0개의 댓글