Kimsora✨
article thumbnail
Published 2023. 2. 23. 09:26
react query React
320x100
반응형
리액트 쿼리를 쓰면 좋다고 해서 공부하려고 하는데 아직 개념이 덜 잡힌거 같다 🥲

React Query는 데이터 Fetching, 캐싱, 동기화, 서버 쪽 데이터 업데이트 등을 쉽게 만들어 주는 React 라이브러리이다.

=>기존에 Redux, Mobx, Recoil과 같은 다양하고 훌륭한 상태 관리 라이브러리들이 있긴 하지만, 클라이언트 쪽의 데이터들을 관리하기에 적합할 순 있어도 서버 쪽의 데이터들을 관리하기에는 적합하지 않은 점들이 있어 해결하기 위해 React-Query가 만들어졌다.

 

React-Query 장점

  • 서버사이드 상태 관리와 관련된 여러 가지 반복적인 작업들을 손쉽게 처리할 수 있다
  • 데이터뿐만 아니라 isIdle, isLoading, isFetching, isSuccess, isError등과 같은 여러 가지 부가적인 상태 값들도 제공한다
  • query key를 통하여 데이터 캐싱과 각 쿼리 간에 디펜던시 조작도 손쉽게 할 수 있다.
  • useEffect로 처리했던 여러 가지 상황들을 refetchOnMount, refetchOnReconnect, refetchOnWindowFocus와 같은 옵션으로 쉽게 처리할 수 있다.
  • keepPreviousData 옵션이나 useInfiniteQuery를 사용하여 페이징 기능도 쉽게 구현할 수 있다.
  • useQueries를 사용하여 병렬처리가 가능하다.
  • 서버 쪽 데이터를 가비지 컬렉션을 이용하여 자동으로 메모리를 관리해준다
  • 구조적 공유를 통해 쿼리의 결과를 기억해준다.

💡클라이언트 상태(Client State)  서버 상태(Server State)는 완전히 다르며클라이언트 상태는 컴포넌트에서 관리하는 각각의 input 값으로 예를 들 수 있고서버 상태는 database에 저장되어있는 데이터로 예를 들 수 있다.

1. Client State

Ownership이 Client에 있다.

  • Client에서 소유하며 온전히 제어가능함
  • 초기값 설정이나 조작에 제약사항 없음
  • 다른 사람들과 공유되지 않으며 Client 내에서 UI/UX 흐름이나 사용자 인터랙션에 따라 변할 수 있음
  • 항상 Client 내에서 최신 상태로 관리됨

2. Server State

Ownership이 Server에 있다.

  • Client에서 제어하거나 소유되지 않는 원격의 공간에서 관리되고 유지됨
  • Fetching이나 Updating에 비동기 API가 필요함
  • 다른 사람들과 공유되는 것으로 사용자가 모르는 사이에 변경될 수 있음
  • 신경 쓰지 않는다면 잠재적으로 "out of date"가 될 가능성을 지님

 

 

React-Query 상태

 fesh : 새롭게 추가된 쿼리 & 만료되지 않은 쿼리 => 컴포넌트가 마운트, 업데이트되어도 데이터 재요청 ❌

 fetching : 요청 중인 쿼리

stale : 만료된 쿼리 => 컴포넌트가 마운트, 업데이트되면 데이터 재요청 ⭕️

inactive : 비활성화된 쿼리 => 특정 시간이 지나면 가비지 컬렉터에 의해 제거

delete - 가비지 컬렉터에 의해 캐시에서 제거된 쿼리

 

QueryClientProvider

  • 리액트 쿼리 사용을 위해 QueryClientProvider 를 최상단에서 감싸야한다
  • 쿼리 인스턴스를 생성 후 client={queryClient} 작성한다
import { QueryClient, QueryClientProvider } from "react-query";

const queryClient = new QueryClient();

export default function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <Home />
    </QueryClientProvider>
  );
}

useQuery

import { useQuery } from "react-query";
// 주로 사용되는 3가지 return 값 외에도 더 많은 return 값들이 있다. 
const { data, isLoading, error } = useQuery(queryKey, queryFn, options)

QueryKey

  • QueryKey 를 기반으로 데이터 캐싱을 관리한다.
  • 문자열 또는 배열로 지정할 수 있다.
// 문자열
useQuery('todos', ...)
// 배열
useQuery(['todos'], ...)
  • 쿼리가 변수에 의존하는 경우에는 QueryKey 에도 해당 변수를 추가해주어야한다.
const { data, isLoading, error } = useQuery(['todos', id], () => axios.get(`http://.../${id}`));

Query Functions

  • useQuery 의 두번째 인자에는 promise 를 반환하는 함수를 넣어주어야한다.
  • 거의 첫번째나 두번째 방식으로 코드를 작성하고 있다.
 useQuery('todos', fetchTodos);
 useQuery(['todos', todoId], () => fetchTodoById(todoId));
 useQuery(['todos', todoId], async () => {
   const data = await fetchTodoById(todoId);
   return data
 });
 useQuery(['todos', todoId], ({ queryKey }) => fetchTodoById(queryKey[1]));

Query Options

enabled (boolean)

  • enabled 는 쿼리가 자동으로 실행되지 않게 설정하는 옵션이다.
  • 아래의 코드는 id가 존재할 때만 쿼리 요청을 한다는 의미의 코드이다.
const { data } = useQuery(
  ['todos', id],
  () => fetchTodoById(id),
  {
    enabled: !!id,
  }
);

retry (boolean | number | (failureCount: number, error: TError) => boolean)

  • retry 는 실패한 쿼리를 재시도하는 옵션이다.
  • 기본적으로 쿼리 실패시 3번 재시도 한다.
  • true 로 설정하면 쿼리 실패시 무한 재시도하고 false로 설정하면 재시도를 하지 않는다.

staleTime (number | Infinity)

  • staleTime 은 데이터가 fresh 상태로 유지되는 시간이다. 해당 시간이 지나면 stale 상태가 된다.
  • default staleTime은 0 이다.
  • fresh 상태에서는 쿼리가 다시 mount 되어도 fetch가 실행되지 않는다.

cacheTime (number | Infinity)

  • cacheTime  inactive 상태인 캐시 데이터가 메모리에 남아있는 시간이다. 이 시간이 지나면 캐시 데이터는 가비지 컬렉터에 의해 메모리에서 제거된다.
  • default cacheTime 은 5분이다.

refetchOnMount (boolean | "always")

  • refetchOnMount 는 데이터가 stale 상태일 경우 마운트 시 마다 refetch를 실행하는 옵션이다.
  • default true
  • always 로 설정하면 마운트 시 마다 매번 refetch 를 실행한다.

refetchOnWindowFocus (boolean | "always")

  • refetchOnWindowFocus 는 데이터가 stale 상태일 경우 윈도우 포커싱 될 때 마다 refetch를 실행하는 옵션이다.
  • 예를 들어, 크롬에서 다른 탭을 눌렀다가 다시 원래 보던 중인 탭을 눌렀을 때도 이 경우에 해당한다. 심지어 F12로 개발자 도구 창을 켜서 네트워크 탭이든, 콘솔 탭이든 개발자 도구 창에서 놀다가 페이지 내부를 다시 클릭했을 때도 이 경우에 해당한다.
  • default true
  • always 로 설정하면 항상 윈도우 포커싱 될 때 마다 refetch를 실행한다는 의미이다.

 

가장기본적이 리액트 쿼리 예제

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

const queryClient = new QueryClient()

export default function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <Example />
    </QueryClientProvider>
  )
}

function Example() {
  const { isLoading, error, data } = useQuery({
    queryKey: ['repoData'],
    queryFn: () =>
      fetch('https://api.github.com/repos/tannerlinsley/react-query').then(
        (res) => res.json(),
      ),
  })

  if (isLoading) return 'Loading...'

  if (error) return 'An error has occurred: ' + error.message

  return (
    <div>
      <h1>{data.name}</h1>
      <p>{data.description}</p>
      <strong>👀 {data.subscribers_count}</strong>{' '}
      <strong>✨ {data.stargazers_count}</strong>{' '}
      <strong>🍴 {data.forks_count}</strong>
    </div>
  )
}

 useState와 useEffect 훅을 사용하지 않는다는 점=> useQuery에는 어플리케이션에서 활용할 수 있는 다양한 값 (로딩 상태, 에러 응답, 반환된 데이터 등)들이 이미 포함되어 있기 때문이다

728x90
반응형
profile

Kimsora✨

@sorarar

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

검색 태그

WH