React query 기본 사용법

Jungmin Lee·2022년 12월 18일
1

react-query

목록 보기
1/1

⛑️ React Query

React Query 공식문서

🎃 react query 사용하는 이유

제가 react query를 사용하게 된 이유는 클라이언트 상태 관리로는 서버 상태관리가 쉽지 않았고, 그것을 해결하기 위해 리덕스로 비동기 처리를 하기에는 너무나도 많은 작업이 필요했기에 이를 간편화 할 방법을 찾다가 react query를 사용하게 되었습니다.
뿐만아니라 react query를 이용함으로써 서스펜스와 에러바운더리를 통해 로딩과 에러를 간단하게 할 수 있었으며, 캐싱이 가능하여 데이터 관리가 편했습니다.

🧣 react query 장단점

  • 캐싱 기능
  • 로딩, 에러처리 간소화 (에러바운더리 + 서스펜스로 더 간단하게 가능)
  • 재사용성
  • 무한 스크롤 (Infinite Queries (opens new window))
  • swr, graphql과 사용법이 매우 비슷 (훅과 사용법이 비슷함)

👻 초기 설정

npm install react-query

or 

yarn add react-query

프로젝트를 생성한 후 react query를 install 해줍니다.

javascript
import "../styles/globals.css";
import type { AppProps } from "next/app";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";

function MyApp({ Component, pageProps }: AppProps) {
  const queryClient = new QueryClient();

  return (
    <QueryClientProvider client={queryClient}>
      <Component {...pageProps} />
    </QueryClientProvider>
  );
}

export default MyApp;

루트 페이지(app.tsx)에 react-query를 세팅합니다.
저는 nextjs로 예제코드를 작성하여 _app.tsx에 세팅했습니다.

🤡 UseQuery

  • userQuery는 데이터를 get 할 때 사용합니다.
  • useQuery(unique Key, Query Function, Query option)
  • unique Key는 고유값이 들어가야 하며, 다른 컴포넌트에서도 해당 키로 호출 가능합니다.
    (배열 형식으로 넣었을 때는 특정 값을 인자로 사용할수도 있습니다.)
  • Query Function는 api 사용할 때 필요한 fetcher함수를 넣는 부분입니다.
  • Query option에서는 옵션을 주로 넣는데 자주 사용하는 옵션은 onSuccess, onError, enable정도가 있습니다.
  • 아래는 간단한 예시입니다.
export default function reactQueryTest(props: Props) {
  const { data, isLoading, isError, error } = useQuery<FetcherApi, AxiosError>(
    ["test-data"],
    () => fetcherApi("get", "/users?page=2"), //인자값을 넣을수도 있고, axios 라이브러리로도 가능
    {
      //성공 (then)
      onSuccess: (resposne) => { 
        console.log("onSuccess");
        console.log(resposne);
      },
	  // 실패 (catch)
      // 네트워크 에러(401,404 등)는 호출이 되지 않고, 서버 api 호출이 실패한 경우만 호출됩니다.
      onError: (error) => {
        console.log("onError");
        console.log(error?.response?.status);
      },
   	  //성공 실패 상관없이 실행 (finally)
      onSettled: () => {
        console.log("onSettled");
      },
    }
  );

  console.log(data);

  if (isLoading) {
    return <div>로딩중...</div>;
  }

  if (isError) {
    return <h1>{error.message}</h1>;
  }

  return (
    <div>
      <h1>{data.page}</h1>
      <h1>{data.per_page}</h1>
      <h1>{data.total}</h1>
      <h1>{data.total_pages}</h1>
    </div>
  );
}
  • data : fetcher api 반환된 response 값
  • error: 에러가 발생했을 때 반환되는 객체
  • isFetching: Request가 in-flight 중일 때 true
  • status, isLoading, isSuccess, isLoading, isError: 현재 query의 상태를 알려줌.
  • refetch: query refetch 해줌
  • remove: query cache 제거

useQuery Option


  const { data, isLoading, isError, error } = useQuery<Post, AxiosError>(
    ["test-data"],
    () => post("get", "/users?page=2"),
    {
      onSuccess:(data: TData) => void,
      onError:(error: TError) => void,
      onSettled:(data?: TData, error?: TError) => void,
      staleTime: number | Infinity,
      cacheTime: number | Infinity,
      enabled: boolean,
      suspense: boolean,
	  retry: boolean | number | (failureCount: number, error: TError) => boolean
	  select: (data: TData) => unknown,
	  keepPreviousData: boolean,
	  refetchInterval:  number | false | ((data: TData | undefined, query: Query) => number | false)
    }
  );
  • onSuccess, onError, onSettled: 성공/실패/완료 시 실행되는 함수
  • cacheTime: 메모리에 얼마만큼 있을 건지 설정
  • staleTime: fresh 상태 유지 시간 설정
  • enabled: 동기적으로 실행할지 유무
  • suspense: 서스펜스를 사용할지 유무
  • retry: query 동작 실패 시, 자동으로 retry할지 결정하는 옵션
  • select: 성공 시 가져온 data를 가공해주는 함수
  • keepPreviousData: 새롭게 fetching 시 이전 데이터 유지 여부
  • refetchInterval: 주기적으로 refetch할지 결정하는 옵션

useQuery Reference

useQueries

프로젝트가 커지면 useQuery를 여러개 사용해야 할 경우가 발생하는데, 그럴 땐 useQueries를 사용 가능합니다.

예제

useQuery 사용

  const {
    data: animalData,
    isLoading: animalLoading,
    isError: animalError,
  } = useQuery<FetcherApi, AxiosError>(["animal"], () =>
    fetcherAnimal("/users?page=1")
  );
  const {
    data: insectData,
    isLoading: insectLoading,
    isError: insectError,
  } = useQuery<FetcherApi, AxiosError>(["insect"], () =>
    fetcherInsect("/users?page=2")
  );
  const {
    data: personData,
    isLoading: personLoading,
    isError: personError,
  } = useQuery<FetcherApi, AxiosError>(["person"], () =>
    fetcherPerson("/users?page=3")
  );
useQueries 사용

  const result = useQueries<FetcherApi[]>([
    {
      queryKey: ["animal"],
      queryFn: () => fetcherAnimal("/users?page=1"),
    },
    {
      queryKey: ["insect"],
      queryFn: () => fetcherInsect("/users?page=2"),
    },
    {
      queryKey: ["person"],
      queryFn: () => fetcherPerson("/users?page=3"),
    },
  ]);

😈 UseMutate

  • POST,PUT,PATCH에 사용하는 api입니다. 사용법은 useQuery랑 비슷합니다.
  • 아래는 간단한 POST 예시입니다.
import { useMutation } from "@tanstack/react-query";
import React, { FormEvent, useState } from "react";
import { fetcherPostApi } from "../api";

type Props = {};

export default function reactQueryMuateTest(props: Props) {
  const [name, setName] = useState<string>("");
  const [job, setJob] = useState<string>("");

  const { mutate, isLoading } = useMutation(fetcherPostApi, {
    onMutate(variables) {
      console.log("onMutate -> ");
      console.log(variables);
    },
    onSuccess: (data, variables, context) => {
      console.log("success -> ", data, variables, context);
    },
    onError: (error, variable, context) => {
      console.log("onError -> ", error, variable, context);
    },
    onSettled: () => {
      console.log("onSettled");
    },
  });

  const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    mutate({
      name: name,
      job: job,
    });
  };

  return (
    <div>
      <h1>React query useMutate 예제</h1>
      {isLoading ? (
        <div>로딩중...</div>
      ) : (
        <form onSubmit={handleSubmit}>
          <input
            type="text"
            value={name}
            onChange={(e) => setName(e.target.value)}
          />
          <input
            type="text"
            value={job}
            onChange={(e) => setJob(e.target.value)}
          />
          <button type="submit">제출하기</button>
        </form>
      )}
    </div>
  );
}
  • mutate : mutation을 실행하는 함수
  • mutateAsync : mutata와 비슷 But Promise 반환
  • reset : mutation 내부 상태 clean

useMutate Option


  const { mutate, isLoading } = useMutation(fetcherPostApi, {
    onMutate(variables) {
      console.log("onMutate -> ");
      console.log(variables);
    },
    onSuccess: (data, variables, context) => {
      console.log("success -> ", data, variables, context);
      // queryClient를 활용해 특정 key의 useQuery를 재호출이 가능합니다.
      queryClient.invalidateQueries("person");

    },
    onError: (error, variable, context) => {
      console.log("onError -> ", error, variable, context);
    },
    onSettled: () => {
      console.log("onSettled");
    },
  });
  • onMutate: post 보내기 전 data를 인자로 받고, post 하기 직전에 실행되는 함수
  • onSuccess, onError, onSettled: 성공/실패/완료 시 실행되는 함수
profile
Front-end developer who never gives up.

0개의 댓글