이전에 프로젝트에 React Query 시작하기에 이어
query key를 기반으로 쿼리 캐시을 관리한다.
react-query에서는 query keys는 내부적으로 데이터를 정확히 캐싱하고 종속성이 변경될 때 자동으로 refetch하는데 사용한다. 또한 데이터 업데이트 후 쿼리를 수동으로 조작할 때 캐시와 상호작용하기 위해서 필요하다.
키는 상수값이 있는 배열부터 변수와 참조형 데이터도 가능하다. 중요한 것은 쿼리는 직렬화가 가능하고 식별이 가능하도록 고유한 값이어야 한다는 것이다.
// 단순한 쿼리 키
useQuery('todos', ...) // ['todos']
useQuery({ queryKey: ['something', 'special'], ... })
// 계층적, 중첩된 데이터에 설명이 필요할 때
useQuery({ queryKey: ['todo', 5, { preview: true }], ...})
useQuery({ queryKey: ['todos', { status, page }], ... })
useQuery({ queryKey: ['todos', { page, status }], ...})
useQuery({ queryKey: ['todos', { page, status, other: undefined }], ... })
useQuery({ queryKey: ['todos', status, page], ... })
useQuery({ queryKey: ['todos', page, status], ...})
useQuery({ queryKey: ['todos', undefined, page, status], ...})
useQuery
위에서 나온 예시처럼 useQuery는 query key와 서버의 데이터를 패치하기 위해서 Promise를 리턴하는 queryFn을 사용해서 데이터를 가져올 수 있다.
서버의 사이드 이펙트를 유발하는 create/update/delete는 mutation(useMutation
)을 사용한다.
import { useQuery } from '@tanstack/react-query'
function App() {
const result = useQuery({ queryKey: ['todos'], queryFn: fetchTodoList })
}
status
result
는 resolve된 데이터나 error를 반환한다. result
는 중요한 몇가지 상태(status)를 반환하게 되는데,
- 쿼리에 아직 데이터가 없는 경우
isLoading
→status === "loading"
- 쿼리에 오류가 발생한 경우
isError
→status === "error"
- 쿼리가 성공하고 데이터가 있는 경우
isSuccess
→status === "success"
isError
인 상태인 경우 오류를 확인할 수 있는 error
와 success
상태일 때 확인할 수 있는 data
속성이 있다.
function Todos() {
const { isLoading, isError, data, error } = useQuery({
queryKey: ['todos'],
queryFn: fetchTodoList,
})
if (isLoading) {
return <span>Loading...</span>
}
if (isError) {
return <span>Error: {error.message}</span>
}
// 여기서는 success 상태임을 확인하고 data가 있음을 짐작할 수 있다.
return (
<ul>
{data.map((todo) => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
)
}
만약, status
로 상태를 확인한다면 다음과 같다.
function Todos() {
const { status, data, error } = useQuery({
queryKey: ['todos'],
queryFn: fetchTodoList,
})
if (status === 'loading') {
return <span>Loading...</span>
}
if (status === 'error') {
return <span>Error: {error.message}</span>
}
return (
<ul>
{data.map((todo) => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
)
}
fetchstatus
result
는 네트워크 연결 상태를 의미하는 fetchStatus를 포함하고 있다. 쿼리가 실행 중 상태인 isFetching
, 어떤 이유로 쿼리가 실행되지 않으며, 대기 중 상태인 isPaused
, 쿼리가 현재 실행 중이 아닌 상태인 isIdle
상태를 나타낸다.
🛑 status와 fatchStatus는 어떻게 다른가요?
위 쿼리의 데이터의 상태를 의미하는 status와는 직교적인 또 다른 상태입니다. 네트워크 연결 상태를 의미하며 필요에 따라 적용할 수 있다. 예를 들면,
success
상태에서는 주로idle
상태이지만, 백그라운드 re-fetch가 일어날 때fetching
상태일 수 있다.- 쿼리가 실행되고 데이터가 없을 경우 보통
loading
상태일 때fetching
fetchStatus를 갖지만 네트워크 연결이 되어 있지 않은 경우paused
상태를 가질 수 있다.
status
는 data
가 있는지 없는지에 대한 상태를 의미하며 fetchStatus
는 쿼리 즉, queryFn
요청이 진행중인지 아닌지에 대한 상태를 의미한다.
✅ React Query v4를 기준으로 작성하였습니다.
v4에서fetchStatus
속성이 추가되었으며,fetching
과 상호 배타적인paused
상태가 추가되었습니다.