useQuery

김동현·2023년 2월 11일
0

React Query

목록 보기
2/5
post-thumbnail

Using React Query

install react-query

먼저 react-query를 설치하기 위해서 아래 명령어를 터미널에 입력해야 합니다.

npm install @tanstack/react-query

Create queryClient & QueryClientProvider

QueryClient 생성자로 쿼리와 캐시를 관리하는 Query Client를 생성하고 <QueryClientProvider> 컴포넌트를 통해 생성한 Query Client를 하위 컴포넌트들이 접근할 수 있도록 최상위 컴포넌트로 감싸주어야 합니다.

모든 하위 컴포넌트들은 Query Client가 갖고 있는 캐시와 모든 기본 옵션을 사용할 수 있게 됩니다.

참고로 <QueryClientProvider>은 React의 Context API를 사용하여 생성된 queryClient를 제공합니다.

import { QueryClient, QueryClientProvider } from '@tanstack/react-query'

// 1. query client 생성
const queryClient = new QueryClient()

function App () {
  return (
    // 2. QueryClientProvider를 통해 하위 컴포넌트들에게 전달
    <QueryClientProvider client={queryClient}>
      ,,,
    </QueryClientProvider>
  )
}

export default App;

Default Options

QueryClient를 생성할 때 default option을 지정해 줄 수 있습니다. new 연산자와 함께 호출할 때 인수로 객체를 전달하고 객체의 defaultOptions 프로퍼티로 queriesmutaions 프로퍼티로 default option들을 설정할 수 있습니다.

import { QueryClient, QueryClientProvider } from '@tanstack/react-query'

const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      /*
      queries: number, // 쿼리 재시도 횟수를 설정, 기본값은 3으로 실패시 3번 재시도
      suspense: boolean, // React의 Suspense 모드 사용 여부를 설정, true 설정시 쿼리가 로딩중일 때 Suspense 모드 사용하여 처리 가능
      staleTime: number, // 쿼리 데이터의 "stale" 기간을 설정
      cacheTime: number, // 쿼리 데이터를 캐시에 저장하는 기간을 설정
      */
    },
    mutations: {
      /*
      onMutate: Function, // 뮤테이션을 시작하기 전에 실행되는 함수를 설정합니다.
      onSuccess: Function, // 뮤테이션 성공 시 실행되는 함수를 설정합니다.
      onError: Function, // 뮤테이션 실패 시 실행되는 함수를 설정합니다.
      */
    }
  }
})

function App () {
  return (
    // 2. QueryClientProvider를 통해 하위 컴포넌트들에게 전달
    <QueryClientProvider client={queryClient}>
        ,,,
    </QueryClientProvider>
  )
}

queryClient 에 설정한 옵션은 모든 쿼리에 전역적으로 설정되지만, useQueryuseMutation 훅에 개별적으로 옵션을 설정한다면 queryClient에 설정한 옵션들은 무시됩니다.

useQueryClient

초기에 new 연산자로 생성한 queryClient에 대해서 매번 재생성하여 사용하지 않습니다.

queryClient는 초기 한 번만 생성 후, QueryClientProvier의 client로 전달한 queryClient를 재사용해야 합니다.

만약 재사용하지 않고 필요할 때 재성성하게 된다면 기존 쿼리에 대한 정보를 갖고 있는 queryClient를 버리고 쿼리에 대한 정보를 갖지 않는 빈 정보를 갖는 queryClient를 사용하는 것과 동일합니다.

생성된 queryClient에 접근하기 위한 훅으로 useQueryClient가 있으며, 호출시 초기 생성한 queryClient를 반환합니다.

import { useQueryClient } from '@tanstack/react-query'

const Component = () => {
  // 기존 QueryClient 반환
  const queryClient = useQueryClient()
  // ,,,
}

export default Component

setQueryData & setQueriesData

queryClient가 제공하는 메서드 중 setQueryDatasetQueriesData를 통해 명시적으로 특정 쿼리에 대한 데이터를 설정할 수 있습니다.

첫 번째 인수로 queryKey, 두 번째 인수로는 해당 쿼리에 설정할 데이터를 전달합니다.

import { useQueryClient } from '@tanstack/react-query'

const Component = () => {
  cosnt queryClient = useQueryClient()
  
  // 특정 쿼리 데이터 설정
  queryClinet.setQueryData([queryKey, ...], TData)
  // ,,,
}

export default Component

setQueryData 메서드를 호출하게 되면 React Query가 해당 쿼리를 구독하고 있는 컴포넌트들을 다시 호출(리렌더링)하게 됩니다.

removeQuery & removeQueries

queryClient가 제공하는 removeQueryremoveQueries 메서드는 특정 쿼리를 명시적을 제거할 수 있습니다.

Using useQuery Hooks

useQuery 훅은 서버 데이터를 GET 요청할 때 사용되는 훅입니다. 기본적으로 비동기 방식으로 동작합니다.

import { useQuery } from '@tanstack/react-query'

const { data, isLoading, error } = useQuery(['key', params...], callbackFn, Options)

즉, useQuery 훅을 통해 GET 요청에 대한 쿼리와 요청에 대한 서버 데이터를 queryClient에 캐싱하기 위해서 사용합니다.

Parameters

  1. ['key', ...deps] : 첫 번째 인수로는 배열을 전달합니다. 배열의 첫 요소는 쿼리를 식별할 수 있는 고유한 키 값을 문자열로 가져야 하며, 두 번째 요소 이후부터는 두 번째 인수로 전달될 콜백함수 내부에서 의존하고 있는 외부 식별자들을 작성합니다.
    이때 쿼리 키 값이 같더라도 의존하고 있는 식별자 값이 일치하지 않는 경우에는 다른 쿼리로 식별하여 별도의 쿼리로 캐싱되고 관리됩니다.

  2. CallbackFn: 서버 데이터를 fetching하는 비동기 함수를 전달해야하며, Promise 객체를 반환하는 함수를 전달합니다.

  3. Options : 객체 타입으로 쿼리에 대한 옵션을 작성할 수 있습니다.

    • staleTime: number : fresh 상태에서 stale 상태로 변경되기 까지의 시간을 설정하며 ms 단위의 숫자값을 작성합니다. 기본값은 0으로 설정되어 있습니다.즉, 모든 쿼리는 fetch된 직후 stale 상태가 됩니다.

    • cacheTime: number : 캐시 만료시간을 설정하는 옵션입니다. 캐시가 만료되면 가비지 컬렉션에 의해 수집되어 클라이언트는 해당 쿼리 데이터를 사용할 수 없게 됩니다. 기본값은 5분으로 설정되어 있습니다.
      이는 컴포넌트가 언마운트된 시점부터 cacheTime 시간 이후에 쿼리가 가바지 컬렉터에게 수집됩니다.

    • refetchOnMount: boolean | 'always' : stale 상태를 갖는 컴포넌트가 마운트되면 새로운 데이터를 re-fetching합니다. 기본값은 true로 설정되어 있습니다.

    • refetchOnWindowFocus: boolean | 'always' : 쿼리가 stale 상태일 때 브라우저 창 포커스되면 새로운 데이터를 re-fetching합니다. 기본값은 true로 설정되어 있습니다.

    • refetchInterval: number : 쿼리가 stale 상태일 때 브라우저 창 포커스되어 있는 경우 지정한 시간 간격으로 새로운 데이터를 re-fetching합니다. 기본값은 0으로 설정되어 있습니다.

    • refetchIntervalInBackground: boolean : 쿼리가 stale 상태일 때 브라우저 창 포커스가 되어 있지 않더라도 지정한 시간 간경으로 새로운 데이터를 re-fetching합니다. 기본값은 false로 설정되어 있습니다.

    • enabled: boolean : 자동 fethcing 동작 유무를 설정합니다. 기본값으로 true로 설정되어 있으며, false로 설정한 경우 자동적으로 데이터를 fethcing하지 않습니다. 이때 useQuery 훅이 반환하는 객체의 refetch 메서드를 통해 수동적으로 fethcing해야 합니다.

    • KeepPreviousData: boolean : true로 설정한 경우 쿼리키가 변경되어 새로운 데이터를 요청(re-fethcing)하는 동안 이전 데이터를 표시합니다.

    • onSuccess: Function : 데이터 fethcing 성공시 실행될 콜백함수를 전달할 수 있습니다.
      콜백함수 인수로는 useQuery 훅의 두 번째 인수로 전달한 콜백함수의 비동기 처리 결과가 전달됩니다.

    • onError: Function : 데이터 fethcing 실패시 실행될 콜백함수를 전달할 수 있습니다.
      인수로 두 번째 인수로 전달한 콜백함수에서 발생한 에러 객체가 전달됩니다.

Returns

useQuery 훅은 객체를 반환하며 객체의 프로퍼티들은 아래와 같습니다.

  1. data : 두 번째 인수로 전달한 콜백함수가 반환한 Promise 객체의 비동기 처리 결과가 바인딩됩니다. 콜백은 비동기로 동작하기 때문에 fetch될 때까지 undefined을 갖고 있습니다.

  2. state : 두 번째 인수로 전달한 콜백함수의 비동기 처리 결과에 대한 상태를 문자열로 갖고 있습니다. "loading", "success", "error" 세 가지 상태값을 갖고 있습니다.

  3. isLoading : 캐싱된 데이터없는 상태에서 데이터를 fetching하고 있는 경우true, 아니면 false 값을 갖습니다.

  4. isFetcing : 캐싱 유무와 상관없이 데이터를 fetching하고 있는 경우true, 아니면 false 값을 갖습니다. isLoading의 상위 집합이 됩니다.

  5. isError : 에러가 발생했는지에 대한 여부를 나타 내는 불리언 값을 갖고 있습니다.
    기본적으로 React Query는 fetching을 세 번 시도하고 세 번 모두 실패한 경우 isError 프로퍼트 값을 true로 설정합니다.

  6. error : 에러가 발생한 경우 에러 객체가 바인딩되며, 에러가 발생하지 않은 경우 undefined 값을 갖습니다.

이외 추가적으로 여러 프로퍼티들을 갖고 있습니다.

Query State

쿼리는 4가지 상태값을 갖습니다.

  1. "fresh" : 새롭게 추가된 쿼리이며 만료되지 않은 쿼리입니다. 컴포넌트가 마운트되거나 리렌더링되더라도 기존 서버 데이터를 사용하며 re-fetching하지 않는 상태입니다.

  2. "fetching" : fetching 중인 쿼리를 나타냅니다.

  3. "stale" : 만료된 쿼리이며 컴포넌트가 컴포넌트가 마운트되거나 리렌더링되는 경우 해당 쿼리를 re-fetching합니다. 즉, stale 상태인 경우에만 데이터를 re-fetching합니다.
    staleTime를 통해 fresh에서 stale 상태로 변경되기 까지의 시간을 의미합니다.

  4. "inactive" : 비활성화된 쿼리이며 캐시의 데이터 만료시간을 설정합니다. 이는 cacheTime 옵션을 통해 설정할 수 있습니다.

useQuery 훅의 동작

  1. 처음 useQuery 훅이 호출되면 쿼리 상태가 fresh 상태가 되며, 첫 번째 인수로 전달한 키로 쿼리와 서버 데이터가 캐싱됩니다.

  2. 이후 staleTime으로 설정한 시간이 경과된 이후 해당 쿼리는 stale 상태가 됩니다. 쿼리가 stale 상태인 경우 re-fetching하고 기존 데이터를 새로운 서버 데이터로 교체합니다.

  3. 컴포넌트가 언마운트된 시점부터 inactive 상태가 되고 cacheTime으로 설정한 시간이 경과된 이후에는 캐싱된 쿼리가 메모리에서 제거되어 가비지 컬렉터로 수집됩니다.

fresh 상태일 때는 re-fethcing을 하지 않고 캐싱된 쿼리 데이터를 사용하며, stale 상태인 경우에는 re-fetching하여 쿼리를 새로운 데이터로 교체합니다. re-fetching되는 동안에는 캐싱된 데이터를 보여주고 re-fetching이 완료되면 새로운 데이터로 교체됩니다.

select Option

useQuery 훅에서 select 옵션을 통해 fetching된 데이터에 대해 가공(필터링)을 할 수 있습니다.

select 함수의 인수로는 fetchin된 데이터가 전달되고 반환값이 최종적으로 data에 바인딩됩니다.

import { useQuery } from '@tanstack/react-query'

const Component = () => {
  const { data } = useQuery([key, ...], queryFn, {
    select: (data) => { ,,, }  // fetching한 데이터를 가공
    });
    // ,,,
}

export default Component

Re-fetching Options

useQuery 훅을 호출하면 컴포넌트가 호출되어 실행되는 시점에 비동기 함수가 실행이 됩니다. 이후 캐싱된 데이터가 변경되는 경우 React Query가 자동적으로 re-fetching을 진행하며, 추가적으로 stale이 0인 쿼리 데이터에 대해서 refetchOnMount, refetchOnWindowFocus와 같은 옵션을 통해서 특정 상황에 대해 re-fethcing을 실행하도록 설정할 수도 있습니다.

import { useQuery } from '@tanstack/react-query'

const Component = () => {
  const { data } = useQuery([key, ...], queryFn, {
    refetchOnMount: true,
    refetchOnWindowFocus: true,
    refetchOnReconnect: true,
    refetchInterval: number
  })
}

export default Component

intialData Option

useQuery 훅에 initialData라는 옵션을 통해 초기 쿼리 데이터를 캐싱할 수 있습니다.

import { useQuery } from '@tanstack/react-query'

const Component = () => {
  const { data } = useQuery([key, ...], queryFn, {
    initialData: TData | () => TData
  })
}

export default Component

placeholder 옵션의 경우 쿼리 상태가 loading일 떄 표시될 데이터입니다. 실질적으로 캐싱되지 않는 데이터이며, initialData 옵션이 설정되지 않은 경우에 동작하게 됩니다.

profile
Frontend Dev

0개의 댓글