React Query 코어 개념 (Query key, useQuery, status, fetchstatus)

김민아·2023년 1월 11일
0

React Query

이전에 프로젝트에 React Query 시작하기에 이어

📌 query keys

query key를 기반으로 쿼리 캐시을 관리한다.
react-query에서는 query keys는 내부적으로 데이터를 정확히 캐싱하고 종속성이 변경될 때 자동으로 refetch하는데 사용한다. 또한 데이터 업데이트 후 쿼리를 수동으로 조작할 때 캐시와 상호작용하기 위해서 필요하다.

키는 상수값이 있는 배열부터 변수와 참조형 데이터도 가능하다. 중요한 것은 쿼리는 직렬화가 가능하고 식별이 가능하도록 고유한 값이어야 한다는 것이다.

// 단순한 쿼리 키
useQuery('todos', ...) // ['todos']
          
useQuery({ queryKey: ['something', 'special'], ... })
          
// 계층적, 중첩된 데이터에 설명이 필요할 때 
useQuery({ queryKey: ['todo', 5, { preview: true }], ...})

🛑 아래 쿼리 키는 동일합니다. (순서 상관x)

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인 상태인 경우 오류를 확인할 수 있는 errorsuccess상태일 때 확인할 수 있는 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 상태를 가질 수 있다.

statusdata가 있는지 없는지에 대한 상태를 의미하며 fetchStatus쿼리 즉, queryFn 요청이 진행중인지 아닌지에 대한 상태를 의미한다.

React Query v4를 기준으로 작성하였습니다.
v4에서 fetchStatus 속성이 추가되었으며, fetching과 상호 배타적인 paused 상태가 추가되었습니다.

출처

0개의 댓글