Reat-Query

React query를 사용해 보자!😉

이지영 2023. 5. 30. 22:53

사용이유 (장점)

  1. 서버 데이터 캐싱
  2. 데이터 패칭 시 로딩, 에러 처리를 한 곳에서 처리 가능
  3. prefetching, retry 등 다양한 옵션
  4. 쉬운 상태 관리
  5. 리덕스대신 비동기 처리를 간편하게 하기위해
  6. 무한 스크롤 ,페이지 네이션과 같은 라이브러리 제공

 UseQuery

- userQuery는 데이터를 get 할 때 사용합니다

- unique Key는 고유값이 들어가야 하며, 다른 컴포넌트에서도 해당 키로 호출 가능합니다.
(배열 형식으로 넣었을 때는 특정 값을 인자로 사용할수도 있습니다.)

-useQuery는 비동기로 작동합니다. 즉, 한 컴포넌트에 여러개의 useQuery가 있다면 하나가 끝나고 다음 useQuery가 실행되는 것이 아닌 두개의 useQuery가 동시에 실행됩니다. 여러개의 비동기 query가 있다면 useQuery보다는 밑에 설명해 드릴 useQueries를 권유드립니다

-Query option에서는 옵션을 주로 넣는데 자주 사용하는 옵션은 onSuccess, onError, enable정도가 있습니다.

❤️사용예시 1❤️

const Todos = () => {
  const { isLoading, isError, data, error } = useQuery("todos", fetchTodoList, {
    refetchOnWindowFocus: false, // react-query는 사용자가 사용하는 윈도우가 다른 곳을 갔다가 다시 화면으로 돌아오면 이 함수를 재실행합니다. 그 재실행 여부 옵션 입니다.
    retry: 0, // 실패시 재호출 몇번 할지
    onSuccess: data => {
      // 성공시 호출
      console.log(data);
    },
    onError: e => {
      // 실패시 호출 (401, 404 같은 error가 아니라 정말 api 호출이 실패한 경우만 호출됩니다.)
      // 강제로 에러 발생시키려면 api단에서 throw Error 날립니다. (참조: https://react-query.tanstack.com/guides/query-functions#usage-with-fetch-and-other-clients-that-do-not-throw-by-default)
      console.log(e.message);
    }
  });

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

  if (isError) {
    return <span>Error: {error.message}</span>;
  }

  return (
    <ul>
      {data.map(todo => (
        <li key={todo.id}>{todo.title}</li>
      ))}
    </ul>
  );
};

❤️사용예시 2❤️

 unique key 활용

unique key를 배열로 넣으면 query함수 내부에서 변수로 사용 가능

❤️사용예시 1❤️

const riot = {
  version: "12.1.1"
};

const result = useQueries([
  {
    queryKey: ["getRune", riot.version],
    queryFn: params => {
      console.log(params); // {queryKey: ['getRune', '12.1.1'], pageParam: undefined, meta: undefined}

      return api.getRunInfo(riot.version);
    }
  },
  {
    queryKey: ["getSpell", riot.version],
    queryFn: () => api.getSpellInfo(riot.version)
  }
]);

❤️사용예시 2❤️

❤️사용예시 3❤️

const users = [1, 2, 3, 4, 5];

const results = useQueries(
  users.map(user => {
    return {
      queryKey: ['getUser', user],
      queryFn: () => axios.get(`https://jsonplaceholder.typicode.com/users/${user}`)
    }
  })
);

 useQueries

promise.all처럼 useQuery를 하나로 묶을 수 있는데, 그것이 useQueries입니다. promise.all과 마찬가지로 하나의 배열에 각 쿼리에 대한 상태 값이 객체로 들어옵니다.

🍕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"),
    },
  ]);

 useMutation

POST,PUT,PATCH에 사용하는 api입니다. 사용법은 useQuery랑 비슷합니다.

❤️사용예시 1❤️

import { useState, useContext, useEffect } from "react";
import loginApi from "api";
import { useMutation } from "react-query";

const Index = () => {
  const [id, setId] = useState("");
  const [password, setPassword] = useState("");

  const loginMutation = useMutation(loginApi, {
    onMutate: variable => {
      console.log("onMutate", variable);
      // variable : {loginId: 'xxx', password; 'xxx'}
    },
    onError: (error, variable, context) => {
      // error
    },
    onSuccess: (data, variables, context) => {
      console.log("success", data, variables, context);
    },
    onSettled: () => {
      console.log("end");
    }
  });

  const handleSubmit = () => {
    loginMutation.mutate({ loginId: id, password });
  };

  return (
    <div>
      {loginMutation.isSuccess ? "success" : "pending"}
      {loginMutation.isError ? "error" : "pending"}
      <input type="text" value={id} onChange={e => setId(e.target.value)} />
      <input
        type="password"
        value={password}
        onChange={e => setPassword(e.target.value)}
      />
      <button onClick={handleSubmit}>로그인</button>
    </div>
  );
};

export default Index;

❤️사용예시 2❤️

  • onMutate: post 보내기 전 data를 인자로 받고, post 하기 직전에 실행되는 함수
  • onSuccess, onError, onSettled: 성공/실패/완료 시 실행되는 함수

 hook 으로 만들어 사용해보자