공식 문서 : https://tanstack.com/query/v4/docs/guides/queries
쿼리는 고유한 key에 연결된 비동기 데이터 소스에 대한 선언적 종속성이다. 쿼리와 Promise 기반 method(GET, POST method 포함)을 함께 사용하여 서버에서 데이터를 가져올 수 있다. 만약 method가 서버의 데이터를 수정하는 경우, mutation을 대신 사용하는게 좋다.
component나 custom hook에서 query를 구독하려면 최소한 다음을 사용하여 useQuery
hook을 호출한다. :
import { useQuery } from '@tanstack/react-query'
function App() {
const info = useQuery(['todos'], fetchTodoList)
}
unique key는 app 전체에서 쿼리를 refetching, caching, sharing 하는데 내부적으로 사용된다.
useQuery
가 반환하는 쿼리 result에는 템플릿 및 기타 데이터 사용에 필요한 쿼리에 대한 모든 정보가 포함되어 있다.
const result = useQuery(['todos'], fetchTodoList)
result
객체에는 생산성을 높이기 위해 알아야할 중요 state들이 포함되어 있다. 쿼리는 지정된 순간에 다음 state중 하나에만 있을 수 있다 :
isLoading
또는 status==='loading'
: 쿼리에 아직 데이터가 없음isError
또는 status==='error'
: 쿼리에 에러 발생isSuccess
또는 status==='success'
: 쿼리가 성공했으며 데이터 사용가능이러한 기본 state 외에도 쿼리 state에 따라 더 많은 정보를 사용할 수 있다.
error
: 쿼리가 isError
state라면 error
property를 통해 에러 사용가능data
: 쿼리가 success
state라면 data
property를 통해 데이터 사용가능대부분의 쿼리의 경우, isLoading
state를 확인한 뒤, isError
state를, 마지막으로 데이터를 사용할 수 있다고 가정하고 success state를 렌더링하는 것으로 충분하다.
function Todos() {
const { isLoading, isError, data, error } = useQuery(['todos'], fetchTodoList)
if (isLoading) {
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>
)
}
만약 isError, isLoading같은 boolean값이 필요하지 않은경우 항상 status
state를 사용할 수 있다.
function Todos() {
const { status, data, error } = useQuery(['todos'], fetchTodoList)
if (status === 'loading') {
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>
)
}
data
에 접근하기 전 loading
과 error
를 확인한 경우 Typescript는 data
의 타입을 올바르게 좁힌다.
result
객체의 status
필드 외에도, 다음과 같은 옵션이 포함된 추가 fetchStatus
property도 얻을 수 있다.
fetchStatus === 'fetching'
: 쿼리가 현재 fetching중.fetchStatus === 'paused'
: 쿼리를 가져오려고 했으나 중단됨.fetchStatus === 'idle'
: 쿼리는 현재 아무 작업도 수행하지 않음.백그라운드 refetch와 stale-while-revalidate(유효기간 만료) 로직은 status와 fetchStatus의 모든 조합을 가능하게 한다. 예를 들어 :
따라서 쿼리는 실제로 데이터를 fetching하지 않고도 loading state일수도 있다. 경험상 다음과 같다 :
data
에 대한 정보를 제공한다 : 있는지, 없는지queryFn
에 대한 정보를 제공한다 : 실행중인지 / 아닌지