[React Query] useQuery select 옵션

apro_xo·2023년 2월 7일
2
post-thumbnail

GET 요청에서 res.data를 반환했었다

useQuery를 사용하여 데이터를 fetching 할 때, axios API 요청 함수에서 return하는 것은 항상 GET 요청 후 받은 응답의 data 값이었다.

왜냐하면 실제로 useQuery를 통해 받아온 응답에서 필요한 것은 response.data 값이기 때문이다. 따라서 아래와 같이 항상 코드를 작성해왔다.

아래의 코드는 jsonplaceholder와 mock API를 통해 실험한 코드이다.

// api.ts
export const functionAPI = {
  fetchDefault: async () => {
    const res = await axios.get("https://jsonplaceholder.typicode.com/todos/1");
    return res.data;
  },
};

📌 useQuery는 커스텀 훅으로 분리하여 모듈화하여 사용하는 예시로 작성하겠다.

// useDefaultFetch.tsx
import React from "react";
import { functionAPI } from "../apis/apifunction";
import { useQuery } from "@tanstack/react-query";

interface Props {
  onSuccess: (data:any) => void;
  onError?: () => void;
}

const useDefaultFetch = ({ onSuccess, onError }: Props) => {
  return useQuery(["fetch_default"], functionAPI.fetchDefault, {
    onSuccess,
    onError
  });
};

export default useDefaultFetch;
// FetchComponent.tsx
import React from "react";
import styled from "styled-components";
import useDefaultFetch from "../hooks/useDefaultFetch";
import { TypeJsonPlaceHolder } from "../typings";

const FetchComponent = () => {
  const onSuccess = (data: TypeJsonPlaceHolder) => {
    console.log("onSuccess: ", data.userId);
  };

  const { data } = useDefaultFetch({ onSuccess });

  return <FetchWrapper>{data?.userId}</FetchWrapper>;
};

export default FetchComponent;

const FetchWrapper = styled.div``;

FetchComponent.tsx에서 커스텀 훅 useDefaultFetch를 사용하고 있고, onSuccess를 통해 GET 요청을 통해 받아온 응답의 data 값의 userId를 console에 찍어주고 있다.

실행 결과는 아래와 같다.

나 혼자 조금씩 거슬렸던 점

apis.ts 파일을 생성하고 axios를 통해 API 요청을 담당하는 함수를 apis.ts에 모두 모으고 분리하여 모듈화 시켜서 사용하는데,
ReactQuery의 useMutate에 사용되는 mutateFn은 항상 Promise를 return 하는 함수여야 한다.

따라서 axios 함수 그 자체를 반환하며 사용했었다.

// apis.ts
import axios from "axios";
import { TypeMock } from "../typings";

export const functionAPI = {
  fetchDefault: async () => {
    const res = await axios.get("https://jsonplaceholder.typicode.com/todos/1");
    return res.data;
  },
  postMock: async (data: TypeMock) => {
    await axios.post(
      "https://62f223b8b1098f15080c163f.mockapi.io/apimainpostings",
      data
    );
  },
};

POST 요청 함수는 Promise를 반환하고 GET 요청 함수는 응답의 data 값을 반환하고,,, 뭔가 통일이 되지 않아 거슬렸다.

물론 GET 함수에서 Promise를 반환하고 onSuccess 같은 곳에서 사용할 때 res.data 와 같은 형태로 사용해도 되긴 하지만 그렇게 하기는 싫었다.
뭔가 조금 있어보이는 방법이 필요했다.

select 옵션

queryFn을 통해 반환 받은 값을 가공, 정제할 수 있는 옵션

select 옵션을 사용해서 조금 멋있게 해결해보자.......!!

// apis.ts
import axios from "axios";

export const functionAPI = {
  fetchDefault: async () => {
    return await axios.get("https://jsonplaceholder.typicode.com/todos/1");
  },

GET 요청 그 자체를 return한다. 즉 Promise를 반환한다..!

import React from "react";
import { functionAPI } from "../apis/apifunction";
import { useQuery } from "@tanstack/react-query";

interface Props {
  onSuccess: (data:any) => void;
  onError?: () => void;
}

const useDefaultFetch = ({ onSuccess, onError }: Props) => {
  return useQuery(["fetch_default"], functionAPI.fetchDefault, {
    onSuccess,
    onError,
    select:data => data.data
  });
};

export default useDefaultFetch;

위의 커스텀 훅에서 select 옵션이 추가 되었다.
queryFn을 통해 반환 받은 값의 data 속성에 접근하여 마치 그 값을 반환 받은 것 처럼 처리해준다.

따라서 사용 시에 번거롭게 data 속성 값에 접근하여 사용하지 않아도 된다.
즉, 데이터를 정제, 가공해준다.

실행 결과는 역시 성공이다.

지금은 비교적 간단한 예시지만, 상황에 따라 데이터를 가공해야할 때, 사용하면 매우 좋을 것 같다.

profile
유능한 프론트엔드 개발자가 되고픈 사람😀

0개의 댓글