React-Query

장현욱(Artlogy)·2022년 12월 13일
0

React

목록 보기
22/24
post-thumbnail

사용하기

패키지 설치

# npm
npm install react-query
# yarn
yarn add react-query

세팅

// src/index.tsx
import React from "react";
import ReactDOM from "react-dom/client";
import "./styles/index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import { QueryClient, QueryClientProvider } from "react-query";
import { ReactQueryDevtools } from "react-query/devtools";

const root = ReactDOM.createRoot(
  document.getElementById("root") as HTMLElement
);

const queryClient: QueryClient = new QueryClient();
// 다음처럼 옵션을 미리 설정할 수 있습니다.
// const queryClient: QueryClient = new QueryClient({defaultOptions: {
//   queries: {
//     retry: 0,
//     useErrorBoundary: true,
//   },
//   mutations: {
//     useErrorBoundary: true,
//   },
// },});


root.render(
  <React.StrictMode>
        <QueryClientProvider client={queryClient}>
          <ReactQueryDevtools initialIsOpen={true}></ReactQueryDevtools>
          <App />
        </QueryClientProvider>
  </React.StrictMode>
);

reportWebVitals();

🔆 devTool은 ReactQuery가 제공하는 개발툴입니다.
필요없다면 제외하셔도 상관없어요

API

useQuery (Get)

Get Method를 위한 훅입니다.

const { isLoading, isError, data, error } = useQuery("key", ()=>api.get(...), 	{
    refetchOnWindowFocus: false, // react-query는 사용자가 사용하는 윈도우가 다른 곳을 갔다가 다시 화면으로 돌아오면 이 함수를 재실행합니다. 그 재실행 여부 옵션 입니다.
    retry: 0, // 실패시 재호출 몇번 할지
    onSuccess: data => {
      // 성공시 호출
      console.log(data);
    },
    onError: e => {
      // 실패시 호출
      console.log(e.message);
    }
  	//...옵션
  	,...options
  });

  if (isLoading) {
    return <span>Loading...</span>;
  }

  if (isError) {
    return <span>Error: {error.message}</span>;
  }
};
  • 첫번째 파라미터는 api를 구분하기 위한 unique한 queryKey값이 들어갑니다.
  • 두번째 파라미터는 api 요청 함수가 들어갑니다. queryFn
  • 세번째 파라미터는 옵션이 들어갑니다. 자주 쓰는 옵션은 다음과 같습니다.
    • enabled : true일경우 옵션에 따라 자동으로 api 요청 함수(두번째 파라미터)가 실행됩니다.
    • staleTime : refetch를 시작하는 주기를 설정 할 수 있습니다. (단위 ms)
    • cacheTime : 캐싱처리가 이루어지는 시간을 설정 할 수 있습니다. (단위 ms)
    • onSuccess : API 요청이 성공 했을 경우 실행 될 콜백함수입니다.
    • onError : API요청이 실패 했을 경우 실행 될 콜백함수입니다.
    • retry : API요청이 실패 했을 경우 다시 실행 될 횟수 입니다. 모든 retry가 소진되어야 onError콜백이 실행됩니다.
    • retryDelay : API요청이 실패 했을 경우 다음 retry까지 대기 할 시간입니다.
    • onSettled : API요청 결과에 상관없이 실행되는 콜백함수입니다.

QueryKey

ReactQuery의 캐시는 직렬화되어 있는 Key값으로 해쉬되어 관리됩니다.

useQuery(['todos', { status, page }], ...)
useQuery(['todos', { page, status }], ...)
useQuery(['todos', { page, status, other: undefined }], ...)

위 코드는 순서와 상관없이 key값이 같기 때문에 모두 같은 쿼리로 취급합니다.
때문에 key값은 서로 다른 쿼리로 쓸 경우 unique해야 합니다.

useQuery(['todos'], fetchTodos)

// 🚨 잘못된 사용 ( 서로다른 쿼리지만 키가 같다.
useInfiniteQuery(['todos'], fetchInfiniteTodos)

// ✅ 사용 가능
useInfiniteQuery(['infiniteTodos'], fetchInfiniteTodos)

QueryKey를 Array형태로 넣으면 QueryFn내부에서 변수로 사용도 가능합니다.

const app = {
  version: "12.1.1"
};

const result = useQuery(
    ["getRune", app.version],
    params => {
      console.log(params); 
  // {queryKey: ['getRune', '12.1.1'], pageParam: undefined, meta: undefined}
      return api.getRunInfo(app.version);
    },
);

Refetch

ReactQuery는 기본적으로 데이터를 fetching 해온 후, 해당 데이터가 stale하다고 판단 될 때 데이터를 refetching합니다. 허나 항상 refetching을 하는 것은 성능상의 문제가 될 수 있기 때문에 사용자에게 최신 데이터를 제공해야하는 상황을 잘 생각해서 사용하여야합니다.
보편적으로 사용자가 최신 데이터를 봐라봐야 하는 상황은 다음과 같습니다.

  • 화면을 보고 있을 때
  • 페이지가 전환 될 때
  • 데이터를 요청 할 때 (이벤트)

리액트 쿼리는 기본적으로 다음과 같은 상황에서 Refetching을 합니다.

  • 브라우저가 포커스 되었을 때 (refetchOnWindowFocus)
  • 마운트 되었을 때 (refetchOnMount)
  • 네트워크가 다시 연결 되었을 때 (refetchOnReconnect)

기본적으로 설정된 것은 위와 같지만 다음옵션설정과 개발자의 커스텀 트리거로 원하는 상황에서 리패치가 가능하게 바꿔줄 수 있습니다.

refetchOnWindowFocus, //default: true
refetchOnMount, //default: true
refetchOnReconnect, //default: true
staleTime, //default: 0
cacheTime, //default: 5분 (60 * 5 * 1000)

useMutation (Post)

Post method를 위한 훅입니다.

// 1
const savePerson = useMutation(mutationFn);

// 2
const savePerson = useMutation({
    mutationFn: mutationFn
})

return 값은 useQuery와 동일합니다. useMutation에선 key값은 optional입니다.
위 처럼 정의를 한후 실제로 이벤트를 발생시킬땐 mutate를 사용합니다.

const savePerson = useMutation((person: Iperson) => 	             axios.post('http://localhost:8080/savePerson', person)); // useMutate 정의
const onSavePerson = () => {
   savePerson.mutate(person); // 데이터 저장
    }

invalidate

mutation으로 데이터를 수정하고 수정된 데이터를 다시 요청하고 싶을 때가 있을겁니다.
그때는 등록된 queryKey의 유효성을 제거해주면 staleTime, cacheTime에 상관없이 서버에 새로운 데이터를 요청할 수 있습니다.

const queryClient = useQueryClient();  // 등록된 quieryClient 가져오기

const savePerson = useMutation((person: Iperson) => axios.post('http://localhost:8080/savePerson', person), {
    onSuccess: () => {
        console.log('onSuccess');
        queryClient.invalidateQueries('persons'); // queryKey 유효성 제거
    },
}); // useMutate 정의

⚡️ 물론 useQuery와 useMutation이 같은 스코프에 정의 되어 있다면 refetch를 호출하여도 됩니다.

0개의 댓글