[React] React Query

비트·2024년 2월 21일

React

목록 보기
10/12
post-thumbnail

React Query

대부분의 기존 상태 관리 라이브러리는 클라이언트 상태 작업에는 적합하지만 비동기 또는 서버 상태 작업에는 그다지 적합하지 않다 .

서버 상태가 전혀 다르기 때문


  • ⚒️ 발생하는 문제

    • 캐싱
    • 동일한 데이터에 대한 여러 요청을 단일 요청으로 중복 제거
    • 백그라운드에서 "오래된" 데이터 업데이트
    • 데이터가 "오래된" 시기 알기
    • 최대한 빠르게 데이터 업데이트 반영
    • 페이지 매김 및 지연 로딩 데이터와 같은 성능 최적화
    • 서버 상태의 메모리 및 가비지 수집 관리
    • 구조적 공유를 통해 쿼리 결과 메모

✏️ 웹 애플리케이션에서 서버 상태 가져오기, 캐싱, 동기화 및 업데이트를 매우 쉽게 만든다.

  • React Query는 서버 상태 관리를 위해 구성이 필요 없이 기본적으로 놀랍도록 잘 작동한다.
  • 애플리케이션이 성장함에 따라 원하는 대로 사용자 정의할 수 있다.
  • 서버 상태 의 까다로운 과제와 장애물을 극복하고 앱 데이터가 사용자를 제어하기 전에 제어할 수 있다.



useQuery

useQuery는 Server State를 읽어오는 hook.

  • isPending or status === 'pending' 쿼리에 아직 데이터가 없다.
  • isError or status === 'error' 쿼리에 오류가 발생.
  • isSuccess or status === 'success' 쿼리가 성공했고 데이터를 사용할 수 있다.

🔍 예시

const {
  data,
  dataUpdatedAt,
  error,
  errorUpdatedAt,
  failureCount,
  failureReason,
  fetchStatus,
  isError,
  isFetched,
  isFetchedAfterMount,
  isFetching,
  isInitialLoading,
  isLoading,
  isLoadingError,
  isPaused,
  isPending,
  isPlaceholderData,
  isRefetchError,
  isRefetching,
  isStale,
  isSuccess,
  refetch,
  status,
} = useQuery(
  {
    queryKey,
    queryFn,
    gcTime,
    enabled,
    networkMode,
    initialData,
    initialDataUpdatedAt,
    meta,
    notifyOnChangeProps,
    placeholderData,
    queryKeyHashFn,
    refetchInterval,
    refetchIntervalInBackground,
    refetchOnMount,
    refetchOnReconnect,
    refetchOnWindowFocus,
    retry,
    retryOnMount,
    retryDelay,
    select,
    staleTime,
    structuralSharing,
    throwOnError,
  },
  queryClient,
)

  • queryKey (필수) : query에 사용할 key (쿼리의 고유 키)

  • queryFn (필수) : 데이터를 요청하는데 사용할 함수 (데이터를 해결하거나, 오류가 발생)

  • cacheTime(gcTime) : 사용되지 않은/비활성 캐시 데이터가 메모리에 남아 있는 시간(밀리초)

  • enabled : 기본값: true / 쿼리가 자동으로 실행할지 여부를 설정

  • refetchOnWindowFocus : 기본값: true / 데이터가 오래된 경우 쿼리가 창 포커스를 다시 가져오도록 설정

  • refetchOnReconnect : 기본값 : true / 데이터가 오래된 경우 재연결 시 쿼리가 다시 가져오도록 설정

  • retry :

    • false => 실패한 쿼리는 기본적으로 재시도하지 않습니다.
    • true => 실패한 쿼리가 계속 재시도됩니다.
    • number => 예를 들어 number로 설정된 경우 3번 실패한 쿼리는 실패한 쿼리 수가 해당 숫자를 충족할 때까지 재시도합니다.


🔍 활용1

const { isInitialLoading, isFetching, error, refetch, remove, data } 
= useQuery(
    ['queryKey'],
    queryFn,
    {
      refetchOnWindowFocus: false,
      retry: 1,
      enabled: false,
      refetchOnReconnect: false,
      cacheTime: 300000
    }
  )

🔍 활용2

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

🔍 활용3

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

useQuery




useMutation

useMutation은 Query와 달리 변형은 일반적으로 데이터를 생성/업데이트/삭제하거나 서버 부작용을 수행하는 데 사용.

  • isIdle or status === 'idle' mutation이 현재 유휴 상태이거나 새로운/재설정 상태.
  • isPending or status === 'pending' mutation이 현재 실행 중.
  • isError or status === 'error' mutation에 오류가 발생.
  • isSuccess or status === 'success' mutation이 성공적이었고 mutation 데이터를 사용할 수 있다.
const {
  data,
  error,
  isError,
  isIdle,
  isLoading,
  isPaused,
  isSuccess,
  failureCount,
  failureReason,
  mutate,
  mutateAsync,
  reset,
  status,
} = useMutation({
  mutationFn,
  cacheTime,
  mutationKey,
  networkMode,
  onError,
  onMutate,
  onSettled,
  onSuccess,
  retry,
  retryDelay,
  useErrorBoundary,
  meta,
})

mutate(variables, {
  onError,
  onSettled,
  onSuccess,
})

  • mutationFn (필수) : 필수이지만 기본 mutation 함수가 정의되지 않은 경우에만 해당

  • onSuccess :

    • 이 함수는 mutation이 성공하면 실행되며 돌연변이 결과가 전달.
    • Promise가 반환되면 계속 진행하기 전에 기다렸다가 해결.
  • onError :

    • 이 함수는 mutation에 오류가 발생하면 실행되고 오류가 전달.
    • Promise가 반환되면 계속 진행하기 전에 기다렸다가 해결
  • onSettled :

    • 이 함수는 변형이 성공적으로 가져오거나 오류가 발생하여 데이터 또는 오류가 전달될 때 실행.
    • Promise가 반환되면 계속 진행하기 전에 기다렸다가 해결.

🔍 활용1

function App() {
  const mutation = useMutation({
    mutationFn: (newTodo) => {
      return axios.post('/todos', newTodo)
    },
  })

  return (
    <div>
      {mutation.isPending ? (
        'Adding todo...'
      ) : (
        <>
          {mutation.isError ? (
            <div>An error occurred: {mutation.error.message}</div>
          ) : null}

          {mutation.isSuccess ? <div>Todo added!</div> : null}

          <button
            onClick={() => {
              mutation.mutate({ id: new Date(), title: 'Do Laundry' })
            }}
          >
            Create Todo
          </button>
        </>
      )}
    </div>
  )
}

useMutation




QueryClient

캐시와 상호 작용하는 데 사용.

import { QueryClient } from '@tanstack/react-query'

const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      staleTime: Infinity,
    },
  },
})

await queryClient.prefetchQuery({ queryKey: ['posts'], queryFn: fetchPosts })

  • queryClient.refetchQueries :

    • 특정 조건에 따라 쿼리를 다시 가져오는 데 사용

    •  // refetch all queries:
       await queryClient.refetchQueries()
      
       // refetch all stale queries:
       // true로 설정하면 오래된 쿼리와 일치.
       // false로 설정하면 새로운 쿼리와 일치.
       await queryClient.refetchQueries({ stale: true })
      
       // refetch all active queries partially matching a query key:
       // 기본값은 all.
       // active 설정하면 활성 쿼리와 일치.
       // inactive 설정하면 비활성 쿼리와 일치.
       await queryClient.refetchQueries({ queryKey: ['posts'], type: 'active' })
      
       // refetch all active queries exactly matching a query key:
       await queryClient.refetchQueries({
         queryKey: ['posts', 1],
         type: 'active',
         exact: true,
      })
  • queryClient.invalidateQueries :

    • 쿼리 키 또는 기능적으로 액세스할 수 있는 다른 쿼리 속성/상태를 기반으로 캐시에서 단일 또는 여러 쿼리를 무효화하고 다시 가져오는 데 사용.

    • 기본적으로 일치하는 모든 쿼리는 즉시 잘못된 것으로 표시되며 활성 쿼리는 백그라운드에서 다시 가져온다.

    • await queryClient.invalidateQueries(
        {
          queryKey: ['posts'],
          exact,
          refetchType: 'active',
        },
        { throwOnError, cancelRefetch },
      )
      
    • refetchType : 'none'

      • 활성 쿼리를 다시 가져오는 것을 원하지 않고 단순히 유효하지 않은 것으로 표시하려는 경우 이 옵션을 사용.
    • refetchType : 'all'

      • 비활성 쿼리도 다시 가져오도록 설정.

QueryClient


profile
Drop the Bit!

0개의 댓글