본문 바로가기

프로젝트

useApi훅에 react-query활용하여 caching기능 넣어보기 (2) - useMutation만으로 useApi 훅 구현 해보기

 

1. useQuery는 쿼리를 즉시 실행하며 필요한 경우 background에서 업데이트를 수행 

mutations는 우리가 변형을 원하는 경우 부를 수 있는 mutate함수를 제공해줌 

 

2. useQuery를 다른 컴포넌트에서 여러번 부를 수 있고, 

동일한 캐시된 결괏값을 부를 수 있다. 

useMutation을 하게 되면 결과를 캐시에 저장하지 않고, 

mutation의 결괏값을 반환해줄 것 이다. 

 

구현해야 할 것은 

가져오는 데이터가 캐싱되도록 하는 것

 

너무 많은 요청을 보내게 되면 api 낭비이므로 

 

useQuery는 생성하면 

생성당시 staleTime을 지정해두면 (default는 0) 

해당 데이터가 stale하다고 판단하여 

 window에서 focus가 되면 refetch를 하게 됨 

staleTime이 지났더라도 focus되기만 해도 refetch되는 동작을 막으려면 

refretchOnWindowFocus옵션을 false로 설정

defaultOptions로 해도 되고, 

useQuery마다 해

 

useQuery를 사용하지 않고 useMutation만 사용할 수 있을까? 

 

 

 

import { useEffect } from 'react';
import { API_FETCHER, ApiMethods } from '@utils/axiosConfig';
import useMutationggu from './useMutationggu';
import { getKeyFromUrl } from '@utils/getNavProps';

interface UseApiParams {
  method?: ApiMethods;
  path?: string;
  data?: any;
  shouldInitFetch?: boolean;
  initialResult?: string;
  gcTime?: number;
}

const useCachingApi = async ({
  method: triggerMethod = 'get',
  path: triggerPath = '',
  data: triggerData = {},
  shouldInitFetch = false,
  // initialResult = '',
  gcTime = 0,
}: UseApiParams) => {
  // }) => {
  const key = getKeyFromUrl(triggerPath);
  //     applyResult = true,
  //     isShowBoundary = true,
  console.log(key);
  const keyArr: string[] = [];
  keyArr.push(key);

  const {
    mutate: trigger,
    data: result,
    isPending: loading,
    error,
  } = useMutationggu(
    keyArr,
    async (data) =>
      await API_FETCHER[triggerMethod as ApiMethods](triggerPath, data),
    gcTime
  );

  useEffect(() => {
    shouldInitFetch && console.log('초기 요청합니다!!');
    shouldInitFetch && trigger(triggerPath, triggerData);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const reqIdentifier = triggerMethod + 'data';

  return { result, loading, reqIdentifier, trigger, error };
};

export default useCachingApi;

 

 

 

 

1. POST요청 

 

 

trigger를 컴포넌트에서 사용 하게 되면 

trigger(data)

 

 

를 하여 요청할 data를 인수에 넣어주고, 

그것은 

 

 

  const {
    mutate: trigger,
    data: result,
    isPending: loading,
    error, 
    ...t생략
  } = useMutationggu(
    keyArr,
    async (data) =>
      await API_FETCHER[triggerMethod as ApiMethods](triggerPath, data),
    gcTime
  );

 

 

이부분에서 API_FETCHER로 가서 

method별로 요청을 보내게 됨

triggerPath는 컴포넌트에서 useApi를 선언할 당시 인수로 넣었던 객체중 path의 key를 사용한다. 

위의 data는 mutate를 사용할 때 첫번째 인수로 넣어주면 들어가게 됨

 

그러니까 사용할 때마다 path가 달라지려면 useApi를 계속해서 새로 선언해주어야 함.

 

 

POST요청 이후 응답 함수 

POST 요청에 대한 응답은 

trigger에 또  option으로 넣어주어도 됨....?

원래는 되는데 한번 useCachingApi에서 useMutationggu로 가게 만든 지금은 모르겠다...!

 

 

 trigger(todo, {
    onSuccess: () => {},
  })

 

 

applyResult = false

결과를 반영하지 않아야 할 때만

onSuccess부분을 조건문 처리 

 

    onSuccess: async () => {
      if (applyResult) {
        queryClient.invalidateQueries({ queryKey: itemId });
        return;
      }
      return;
    },

 

 

나머지는 true가 default 값 

 

 

isShowBoundary true가 default

 

 

 

    onError: async (error, variables, context) => {
      isShowBoundary && showBoundary(error);
    },

 

 

App.tsx

 <QueryErrorResetBoundary>
      <ErrorBoundary onReset={reset} fallback={<Error />}>

 

 

 

 

2. GET요청 

 

    method get이고 gcTime적용해야 할때는 기존 값을 반환해서 캐싱을 적용해야 함

 

onMutate: async () => {
      if (method === 'get' && gc > 0) {
        await queryClient.cancelQueries({ queryKey: itemId });

        // 기존 Query를 가져오는 함수 ( 존재하지 않으면 undefind 반환 )
        const previousValue = queryClient.getQueryData(itemId);

        //optimistic UI 현재는 필요없음
        // if (previousValue) {
        //   // setQueryData(): Query의 캐시된 데이터를 즉시 업데이트하는 동기 함수 ( Query가 존재하지 않으면 생성 )
        //   // 전달받은 variables값을 즉시 새로운 데이터로 업데이트
        //   queryClient.setQueryData(itemId, (oldData) => [...oldData, variables]);
        // }

        // 이전 값 리턴
        return { previousValue };
      }
    },

 

 

3. UPDATE 요청 

 

data를 trigger의 첫번째 argument로 보내서 

요청을 보내고, 

성공/실패 여부에 따라 

onSuccess 함수 사용

onError일때 함수를 넣어도 되고 안넣어도 됨

(onError일때 toast를 보여줘도 될듯)

 

4. DELETE요청

 

UPDATE와 동일