react-query v4 : Queries

👾·2022년 8월 3일
0

react-query

목록 보기
3/27
post-thumbnail

공식 문서 : https://tanstack.com/query/v4/docs/guides/queries

Queries

Query Basics

쿼리는 고유한 key에 연결된 비동기 데이터 소스에 대한 선언적 종속성이다. 쿼리와 Promise 기반 method(GET, POST method 포함)을 함께 사용하여 서버에서 데이터를 가져올 수 있다. 만약 method가 서버의 데이터를 수정하는 경우, mutation을 대신 사용하는게 좋다.

component나 custom hook에서 query를 구독하려면 최소한 다음을 사용하여 useQuery hook을 호출한다. :

  • 쿼리의 unique key
  • 다음과 같이 Promise를 반환하는 함수 : resolve data, throw error
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에 접근하기 전 loadingerror를 확인한 경우 Typescript는 data의 타입을 올바르게 좁힌다.

FetchStatus

result 객체의 status 필드 외에도, 다음과 같은 옵션이 포함된 추가 fetchStatus property도 얻을 수 있다.

  • fetchStatus === 'fetching' : 쿼리가 현재 fetching중.
  • fetchStatus === 'paused' : 쿼리를 가져오려고 했으나 중단됨.
  • fetchStatus === 'idle' : 쿼리는 현재 아무 작업도 수행하지 않음.

Why two different states?

백그라운드 refetch와 stale-while-revalidate(유효기간 만료) 로직은 status와 fetchStatus의 모든 조합을 가능하게 한다. 예를 들어 :

  • success status의 쿼리는 일반적으로 idle fetchStatus에 있지만, 백그라운드 refetch가 발생하는 중에는 fetching에 있을수도 있다.
  • mount하고 데이터가 없는 쿼리는 일반적으로 loading status이며 fetching fetchStatus이지만, 네트워크 연결이 없는 경우 paused일수도 있다.

따라서 쿼리는 실제로 데이터를 fetching하지 않고도 loading state일수도 있다. 경험상 다음과 같다 :

  • status는 data에 대한 정보를 제공한다 : 있는지, 없는지
  • fetchStatus는 queryFn에 대한 정보를 제공한다 : 실행중인지 / 아닌지

0개의 댓글