[React Query] 리액트 쿼리 시작하기 (useQuery)

2023. 3. 6. 11:08프레임워크(Framework)/React

React Query (리액트 쿼리)

리액트에서 비동기 로직을 리액트스럽게 다룰 수 있게 해주는 라이브러리이다.
server state를 아주 효율적으로 관리할 수 있다.
기존에 isLoading, isError, refetch, 데이터 캐싱 등 개발자가 직접 구현하려면 꽤 귀찮거나 까다로웠던 기능을 제공해준다.

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를 실행한다는 의미이다.


예제 코드

// 유저 정보를 가져오는 쿼리이다.
const { data: userInfo } = useQuery(
  ['user'],
  getUser,
  {
    refetchOnWindowFocus: true,
    staleTime: 60 * 1000, // 1분
  }
)


● QueryClient defaultOptions 설정으로 refetch 기능들을 다 false로 꺼버렸을 경우에는 refetch 기능이 실행되지 않는다. 그럴 경우엔 refetchOnWindowFocus 옵션이 실행되게끔 true로 설정하면 된다.
● fresh 상태인 1분 동안은 아무리 다른 탭을 왔다갔다해도 fetch 요청을 하지 않는다.

 

refetchOnReconnect (boolean | "always")

● refetchOnReconnect 는 데이터가 stale 상태일 경우 재 연결 될 때 refetch를 실행하는 옵션이다.
● default true
● always 도 위에 두 옵션 처럼 쿼리가 매번 재 연결될 때 마다 refetch를 실행한다.

 

onSuccess ((data: TDdata) => void)
● onSuccess 는 쿼리 성공 시 실행되는 함수이다.
● 매개변수 data는 성공 시 서버에서 넘어오는 response 값이다.

 

onError ((error: TError) => void)
● onError 는 쿼리 실패 시 실행되는 함수이다.
● 매개변수로 에러 값을 받을 수 있다.


예제 코드

const { data: userInfo } = useQuery(
  ['user'],
  getUser,
  {
    refetchOnWindowFocus: true,
    staleTime: 60 * 1000, // 1분
    onError: (error) => {
      if (error.response?.data.code === 401) {
        //...
      }
    },
  }
)


onSettled ((data?: TData, error?: TError) => void)
● onSettled 는 쿼리가 성공해서 성공한 데이터가 전달되거나, 실패해서 에러가 전달 될 때 실행되는 함수이다.
● 매개변수로 성공 시엔 성공 데이터, 실패 시에는 에러가 전달된다.

 

initialData (TData | () => TData)
● initialData 를 설정하면 쿼리 캐시의 초기 데이터로 사용된다. (쿼리가 아직 생성되지 않았거나 캐시되지 않았을 때)
● staleTime 이 설정되지 않은 경우 초기 데이터는 기본적으로 stale 상태로 간주한다.

'프레임워크(Framework) > React' 카테고리의 다른 글

react-query  (0) 2023.03.12
React 기본 파일(index.js, App.js, index.html)  (0) 2023.03.10
React Hooks란?  (0) 2023.03.05
Hooks  (0) 2023.02.18
State and Lifecycle  (0) 2023.02.18