본문으로 건너뛰기

쿼리

쿼리 기본 사항

쿼리는 고유 키에 연결된 비동기 데이터 소스에 대한 선언적 의존성입니다. 쿼리는 서버에서 데이터를 가져오기 위해 모든 Promise 기반 메서드(GET 및 POST 메서드 포함)와 함께 사용할 수 있습니다. 메서드가 서버의 데이터를 수정한다면 대신 뮤테이션을 사용하는 것이 좋습니다.

컴포넌트 또는 커스텀 훅에서 쿼리를 구독하려면 최소한 다음 항목과 함께 useQuery 훅을 호출합니다:

  • 쿼리의 고유 키
  • 다음을 수행하는 Promise를 반환하는 함수입니다:
    • 데이터를 이행합니다. 또는
    • 오류를 발생시킵니다
import { useQuery } from '@tanstack/react-query'

function App() {
const info = useQuery({ queryKey: ['todos'], queryFn: fetchTodoList })
}

제공하는 고유 키는 애플리케이션 전반에서 쿼리를 다시 가져오고, 캐시하고, 공유하는 데 내부적으로 사용됩니다.

useQuery에서 반환된 쿼리 결과에는 템플릿 구성과 그 밖의 데이터 사용에 필요한 쿼리의 모든 정보가 포함됩니다:

const result = useQuery({ queryKey: ['todos'], queryFn: fetchTodoList })

result 객체에는 생산적으로 작업하기 위해 알아야 할 몇 가지 매우 중요한 상태가 포함되어 있습니다. 쿼리는 어떤 순간이든 다음 상태 중 하나에만 있을 수 있습니다:

  • isPending 또는 status === 'pending' - 쿼리에 아직 데이터가 없습니다
  • isError 또는 status === 'error' - 쿼리에서 오류가 발생했습니다
  • isSuccess 또는 status === 'success' - 쿼리가 성공했으며 데이터를 사용할 수 있습니다

이러한 주요 상태 외에도 쿼리 상태에 따라 더 많은 정보를 사용할 수 있습니다:

  • error - 쿼리가 isError 상태이면 error 속성을 통해 오류를 사용할 수 있습니다.
  • data - 쿼리가 isSuccess 상태이면 data 속성을 통해 데이터를 사용할 수 있습니다.
  • isFetching - 어떤 상태에서든 쿼리가 가져오기 중이면(백그라운드에서 다시 가져오기 포함) isFetchingtrue입니다.

대부분의 쿼리에서는 일반적으로 isPending 상태를 확인한 다음 isError 상태를 확인하고, 마지막으로 데이터가 사용 가능하다고 가정하여 성공 상태를 렌더링하는 것으로 충분합니다:

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>
)
}

불리언이 마음에 들지 않는다면 언제든 status 상태도 사용할 수 있습니다:

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>
)
}

TypeScript에 접근하기 전에 pendingerror를 확인했다면 data의 타입도 올바르게 좁힙니다.

FetchStatus

status 필드 외에도 다음 옵션이 포함된 추가 fetchStatus 속성이 제공됩니다:

  • fetchStatus === 'fetching' - 쿼리가 현재 데이터를 가져오는 중입니다.
  • fetchStatus === 'paused' - 쿼리가 가져오기를 원했지만 일시 중지되었습니다. 자세한 내용은 네트워크 모드 가이드를 참조하세요.
  • fetchStatus === 'idle' - 쿼리가 현재 아무 작업도 수행하지 않습니다.

왜 서로 다른 상태가 두 개인가요?

백그라운드 다시 가져오기와 stale-while-revalidate 로직을 통해 statusfetchStatus의 모든 조합을 사용할 수 있습니다. 예를 들면 다음과 같습니다:

  • success 상태의 쿼리는 일반적으로 idle fetchStatus에 있지만, 백그라운드에서 다시 가져오기가 진행 중이면 fetching에 있을 수도 있습니다.
  • 마운트되며 데이터가 없는 쿼리는 일반적으로 pending 상태이고 fetching fetchStatus이지만, 네트워크 연결이 없으면 paused일 수도 있습니다.

따라서 실제로 데이터를 가져오지 않아도 쿼리가 pending 상태일 수 있다는 점에 유의하세요. 경험칙은 다음과 같습니다:

  • statusdata에 관한 정보, 즉 존재 여부를 제공합니다.
  • fetchStatusqueryFn에 관한 정보를 제공합니다. 실행 중인지 여부를 알려줍니다.

추가 자료

상태 확인을 수행하는 다른 방법은 TkDodo의 글을 살펴보세요.