
대부분의 기존 상태 관리 라이브러리는 클라이언트 상태 작업에는 적합하지만 비동기 또는 서버 상태 작업에는 그다지 적합하지 않다 .
서버 상태가 전혀 다르기 때문
⚒️ 발생하는 문제
- 캐싱
- 동일한 데이터에 대한 여러 요청을 단일 요청으로 중복 제거
- 백그라운드에서 "오래된" 데이터 업데이트
- 데이터가 "오래된" 시기 알기
- 최대한 빠르게 데이터 업데이트 반영
- 페이지 매김 및 지연 로딩 데이터와 같은 성능 최적화
- 서버 상태의 메모리 및 가비지 수집 관리
- 구조적 공유를 통해 쿼리 결과 메모
useQuery는 Server State를 읽어오는 hook.
isPendingorstatus === 'pending'쿼리에 아직 데이터가 없다.isErrororstatus === 'error'쿼리에 오류가 발생.isSuccessorstatus === 'success'쿼리가 성공했고 데이터를 사용할 수 있다.
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,
)
queryKey (필수) : query에 사용할 key (쿼리의 고유 키)
queryFn (필수) : 데이터를 요청하는데 사용할 함수 (데이터를 해결하거나, 오류가 발생)
cacheTime(gcTime) : 사용되지 않은/비활성 캐시 데이터가 메모리에 남아 있는 시간(밀리초)
enabled : 기본값: true / 쿼리가 자동으로 실행할지 여부를 설정
refetchOnWindowFocus : 기본값: true / 데이터가 오래된 경우 쿼리가 창 포커스를 다시 가져오도록 설정
refetchOnReconnect : 기본값 : true / 데이터가 오래된 경우 재연결 시 쿼리가 다시 가져오도록 설정
retry :
false => 실패한 쿼리는 기본적으로 재시도하지 않습니다.true => 실패한 쿼리가 계속 재시도됩니다.number => 예를 들어 number로 설정된 경우 3번 실패한 쿼리는 실패한 쿼리 수가 해당 숫자를 충족할 때까지 재시도합니다.const { isInitialLoading, isFetching, error, refetch, remove, data }
= useQuery(
['queryKey'],
queryFn,
{
refetchOnWindowFocus: false,
retry: 1,
enabled: false,
refetchOnReconnect: false,
cacheTime: 300000
}
)
function Todos() {
const { isPending, isError, data, error } = useQuery({
queryKey: ['todos'],
queryFn: fetchTodoList,
})
if (isPending) {
return <span>Loading...</span>
}
if (isError) {
return <span>Error: {error.message}</span>
}
// We can assume by this point that `isSuccess === true`
return (
<ul>
{data.map((todo) => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
)
}
function Todos() {
const { status, data, error } = useQuery({
queryKey: ['todos'],
queryFn: fetchTodoList,
})
if (status === 'pending') {
return <span>Loading...</span>
}
if (status === 'error') {
return <span>Error: {error.message}</span>
}
// also status === 'success', but "else" logic works, too
return (
<ul>
{data.map((todo) => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
)
}
useMutation은 Query와 달리 변형은 일반적으로 데이터를 생성/업데이트/삭제하거나 서버 부작용을 수행하는 데 사용.
isIdleorstatus === 'idle'mutation이 현재 유휴 상태이거나 새로운/재설정 상태.isPendingorstatus === 'pending'mutation이 현재 실행 중.isErrororstatus === 'error'mutation에 오류가 발생.isSuccessorstatus === 'success'mutation이 성공적이었고 mutation 데이터를 사용할 수 있다.
const {
data,
error,
isError,
isIdle,
isLoading,
isPaused,
isSuccess,
failureCount,
failureReason,
mutate,
mutateAsync,
reset,
status,
} = useMutation({
mutationFn,
cacheTime,
mutationKey,
networkMode,
onError,
onMutate,
onSettled,
onSuccess,
retry,
retryDelay,
useErrorBoundary,
meta,
})
mutate(variables, {
onError,
onSettled,
onSuccess,
})
mutationFn (필수) : 필수이지만 기본 mutation 함수가 정의되지 않은 경우에만 해당
onSuccess :
onError :
onSettled :
function App() {
const mutation = useMutation({
mutationFn: (newTodo) => {
return axios.post('/todos', newTodo)
},
})
return (
<div>
{mutation.isPending ? (
'Adding todo...'
) : (
<>
{mutation.isError ? (
<div>An error occurred: {mutation.error.message}</div>
) : null}
{mutation.isSuccess ? <div>Todo added!</div> : null}
<button
onClick={() => {
mutation.mutate({ id: new Date(), title: 'Do Laundry' })
}}
>
Create Todo
</button>
</>
)}
</div>
)
}
캐시와 상호 작용하는 데 사용.
import { QueryClient } from '@tanstack/react-query'
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: Infinity,
},
},
})
await queryClient.prefetchQuery({ queryKey: ['posts'], queryFn: fetchPosts })
queryClient.refetchQueries :
특정 조건에 따라 쿼리를 다시 가져오는 데 사용
// refetch all queries:
await queryClient.refetchQueries()
// refetch all stale queries:
// true로 설정하면 오래된 쿼리와 일치.
// false로 설정하면 새로운 쿼리와 일치.
await queryClient.refetchQueries({ stale: true })
// refetch all active queries partially matching a query key:
// 기본값은 all.
// active 설정하면 활성 쿼리와 일치.
// inactive 설정하면 비활성 쿼리와 일치.
await queryClient.refetchQueries({ queryKey: ['posts'], type: 'active' })
// refetch all active queries exactly matching a query key:
await queryClient.refetchQueries({
queryKey: ['posts', 1],
type: 'active',
exact: true,
})
queryClient.invalidateQueries :
쿼리 키 또는 기능적으로 액세스할 수 있는 다른 쿼리 속성/상태를 기반으로 캐시에서 단일 또는 여러 쿼리를 무효화하고 다시 가져오는 데 사용.
기본적으로 일치하는 모든 쿼리는 즉시 잘못된 것으로 표시되며 활성 쿼리는 백그라운드에서 다시 가져온다.
await queryClient.invalidateQueries(
{
queryKey: ['posts'],
exact,
refetchType: 'active',
},
{ throwOnError, cancelRefetch },
)
refetchType : 'none'
refetchType : 'all'