먼저 react-query를 설치하기 위해서 아래 명령어를 터미널에 입력해야 합니다.
npm install @tanstack/react-query
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;
QueryClient
를 생성할 때 default option을 지정해 줄 수 있습니다. new 연산자와 함께 호출할 때 인수로 객체를 전달하고 객체의 defaultOptions
프로퍼티로 queries
와 mutaions
프로퍼티로 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
에 설정한 옵션은 모든 쿼리에 전역적으로 설정되지만,useQuery
나useMutation
훅에 개별적으로 옵션을 설정한다면queryClient
에 설정한 옵션들은 무시됩니다.
초기에 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
queryClient
가 제공하는 메서드 중 setQueryData
와 setQueriesData
를 통해 명시적으로 특정 쿼리에 대한 데이터를 설정할 수 있습니다.
첫 번째 인수로 queryKey, 두 번째 인수로는 해당 쿼리에 설정할 데이터를 전달합니다.
import { useQueryClient } from '@tanstack/react-query'
const Component = () => {
cosnt queryClient = useQueryClient()
// 특정 쿼리 데이터 설정
queryClinet.setQueryData([queryKey, ...], TData)
// ,,,
}
export default Component
setQueryData
메서드를 호출하게 되면 React Query가 해당 쿼리를 구독하고 있는 컴포넌트들을 다시 호출(리렌더링)하게 됩니다.
queryClient가 제공하는 removeQuery
와 removeQueries
메서드는 특정 쿼리를 명시적을 제거할 수 있습니다.
useQuery
훅은 서버 데이터를 GET 요청할 때 사용되는 훅입니다. 기본적으로 비동기 방식으로 동작합니다.
import { useQuery } from '@tanstack/react-query'
const { data, isLoading, error } = useQuery(['key', params...], callbackFn, Options)
즉, useQuery
훅을 통해 GET 요청에 대한 쿼리와 요청에 대한 서버 데이터를 queryClient에 캐싱하기 위해서 사용합니다.
['key', ...deps]
: 첫 번째 인수로는 배열을 전달합니다. 배열의 첫 요소는 쿼리를 식별할 수 있는 고유한 키 값을 문자열로 가져야 하며, 두 번째 요소 이후부터는 두 번째 인수로 전달될 콜백함수 내부에서 의존하고 있는 외부 식별자들을 작성합니다.
이때 쿼리 키 값이 같더라도 의존하고 있는 식별자 값이 일치하지 않는 경우에는 다른 쿼리로 식별하여 별도의 쿼리로 캐싱되고 관리됩니다.
CallbackFn
: 서버 데이터를 fetching하는 비동기 함수를 전달해야하며, Promise 객체를 반환하는 함수를 전달합니다.
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 실패시 실행될 콜백함수를 전달할 수 있습니다.
인수로 두 번째 인수로 전달한 콜백함수에서 발생한 에러 객체가 전달됩니다.
useQuery
훅은 객체를 반환하며 객체의 프로퍼티들은 아래와 같습니다.
data
: 두 번째 인수로 전달한 콜백함수가 반환한 Promise 객체의 비동기 처리 결과가 바인딩됩니다. 콜백은 비동기로 동작하기 때문에 fetch될 때까지 undefined
값을 갖고 있습니다.
state
: 두 번째 인수로 전달한 콜백함수의 비동기 처리 결과에 대한 상태를 문자열로 갖고 있습니다. "loading"
, "success"
, "error"
세 가지 상태값을 갖고 있습니다.
isLoading
: 캐싱된 데이터없는 상태에서 데이터를 fetching하고 있는 경우에 true
, 아니면 false
값을 갖습니다.
isFetcing
: 캐싱 유무와 상관없이 데이터를 fetching하고 있는 경우에 true
, 아니면 false
값을 갖습니다. isLoading
의 상위 집합이 됩니다.
isError
: 에러가 발생했는지에 대한 여부를 나타 내는 불리언 값을 갖고 있습니다.
기본적으로 React Query는 fetching을 세 번 시도하고 세 번 모두 실패한 경우 isError
프로퍼트 값을 true
로 설정합니다.
error
: 에러가 발생한 경우 에러 객체가 바인딩되며, 에러가 발생하지 않은 경우 undefined
값을 갖습니다.
이외 추가적으로 여러 프로퍼티들을 갖고 있습니다.
쿼리는 4가지 상태값을 갖습니다.
"fresh"
: 새롭게 추가된 쿼리이며 만료되지 않은 쿼리입니다. 컴포넌트가 마운트되거나 리렌더링되더라도 기존 서버 데이터를 사용하며 re-fetching하지 않는 상태입니다.
"fetching"
: fetching 중인 쿼리를 나타냅니다.
"stale"
: 만료된 쿼리이며 컴포넌트가 컴포넌트가 마운트되거나 리렌더링되는 경우 해당 쿼리를 re-fetching합니다. 즉, stale 상태인 경우에만 데이터를 re-fetching합니다.
staleTime
를 통해 fresh에서 stale 상태로 변경되기 까지의 시간을 의미합니다.
"inactive"
: 비활성화된 쿼리이며 캐시의 데이터 만료시간을 설정합니다. 이는 cacheTime
옵션을 통해 설정할 수 있습니다.
처음 useQuery
훅이 호출되면 쿼리 상태가 fresh 상태가 되며, 첫 번째 인수로 전달한 키로 쿼리와 서버 데이터가 캐싱됩니다.
이후 staleTime
으로 설정한 시간이 경과된 이후 해당 쿼리는 stale 상태가 됩니다. 쿼리가 stale 상태인 경우 re-fetching하고 기존 데이터를 새로운 서버 데이터로 교체합니다.
컴포넌트가 언마운트된 시점부터 inactive 상태가 되고 cacheTime
으로 설정한 시간이 경과된 이후에는 캐싱된 쿼리가 메모리에서 제거되어 가비지 컬렉터로 수집됩니다.
fresh 상태일 때는 re-fethcing을 하지 않고 캐싱된 쿼리 데이터를 사용하며, stale 상태인 경우에는 re-fetching하여 쿼리를 새로운 데이터로 교체합니다. re-fetching되는 동안에는 캐싱된 데이터를 보여주고 re-fetching이 완료되면 새로운 데이터로 교체됩니다.
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
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
useQuery
훅에 initialData
라는 옵션을 통해 초기 쿼리 데이터를 캐싱할 수 있습니다.
import { useQuery } from '@tanstack/react-query'
const Component = () => {
const { data } = useQuery([key, ...], queryFn, {
initialData: TData | () => TData
})
}
export default Component
placeholder
옵션의 경우 쿼리 상태가 loading일 떄 표시될 데이터입니다. 실질적으로 캐싱되지 않는 데이터이며,initialData
옵션이 설정되지 않은 경우에 동작하게 됩니다.