Web Tech/library

React Query

걍가영 2024. 6. 11. 16:30

React Query는 React에서 비동기 데이터를 관리하기 위한 라이브러리이며,  API 요청 및 상태 관리를 위해 규격화된 방식을 제공한다.
서버의 상태를 불러오고, 캐싱하며, 지속적으로 동기화하고 업데이트 하는 작업을 쉽게 도와주는 강점이 있다.

React Query의 요청 방식

Query 요청

  • Query 함수를 사용해서 데이터를 가져오고 캐싱할 수 있으며, 데이터 패칭용으로 사용되며, 보통은 GET 방식때 사용한다.
  • useQuery Hook은 요청마다 (API마다) 구분되는 Unique Key(Query Key)를 필요로 하며, React Query는 이 Unique Key로 서버 상태(API Response)를 로컬에 캐시하고 관리한다.
  • (useQueries, useInfiniteQuery 같은 Hook들도 제공함)
// 가장 기본적인 형태의 React Query useQuery Hook 사용 예시
const { data } = useQuery(
  queryKey, // 이 Query 요청에 대한 응답 데이터를 캐시할 때 사용할 Unique Key (required)
  fetchFn, // 이 Query 요청을 수행하기 위한 Promise를 Return 하는 함수 (required)
  options, // useQuery에서 사용되는 Option 객체 (optional)
);
export const useFetch = <T, ST = T>(
  url: string,
  params?: object,
  config?: UseQueryOptions<T, AxiosError<APIError>, ST, QueryKeyT> | undefined
): UseQueryResult<ST, AxiosError<APIError>> => {
  const context = useQuery<T, AxiosError<APIError>, ST, QueryKeyT>({
    queryKey: [url, params],
    queryFn: fetcher,
    enabled: !!url,
    initialData: undefined,
    ...config,
  });

  return context;
};
export const useGetQuery = (Request: Request, enabled?: boolean) =>
  useFetch<Response>(Request URL, Request, {
    enabled,
  });

 


 

Mutation 요청

  • 함수를 사용하여 데이터를 업데이트하고 캐시를 업데이트 할 수 있다.
  • 보통 POST, PUT, DELETE 요청과 같이 서버에 Side Effect를 발생시켜 서버의 상태를 변경시킬 때 사용한다.
// 가장 기본적인 형태의 React Query useMutation Hook 사용 예시 
const { mutate } = useMutation(
  mutationFn, // 이 Mutation 요청을 수행하기 위한 Promise를 Return 하는 함수 (required) 
  options, // useMutation에서 사용되는 Option 객체 (optional) 
);
const useGenericMutation = <T, S>(
  func: (data: T | S) => Promise<AxiosResponse<S>>,
  url: string,
  params?: object,
  updater?: ((oldData?: T | undefined, newData?: S) => T) | undefined
) => {
  const queryClient = useQueryClient();

  return useMutation<AxiosResponse, AxiosError<APIError>, T | S>({
    mutationFn: func,
    onMutate: async (data) => {
      await queryClient.cancelQueries([url, params]);

      const previousData = queryClient.getQueryData([url, params]);

      queryClient.setQueryData<T>([url, params], (oldData) => {
        return updater ? updater(oldData, data as S) : (data as T);
      });

      return previousData;
    },
    onError: (_, __, context) => {
      queryClient.setQueryData([url, params], context);
    },
    onSettled: () => {
      queryClient.invalidateQueries([url, params]);
    },
  });
};
export const useMutationFunc = async (Request:Request) => {
  const { data } = await api.post(Request URL, Request);
  return data;
};
 const { mutate: useMutationFunction } = useMutation({
    mutationFn: useMutationFunc,
    onSuccess: ({ id }) => {
      refresh(pathToUrl(apiRoutes.getEventBannerDetail, { id }));
      router.push({
        pathname: "/event/banner/[id]",
        query: { id: id, mode: PAGETYPE.DETAIL },
      });
    },
    onError: handleError,
  });