거의 알고리즘 일기장

custom useAxios hook 본문

web

custom useAxios hook

건우권 2021. 11. 11. 17:29

https://dev.to/ms_yogii/useaxios-a-simple-custom-hook-for-calling-apis-using-axios-2dkj#final-code

 

useAxios : A simple custom hook for calling APIs using axios

Hello folks, Frontend apps are not complete if there are no api calls involved and calling an api b...

dev.to

이런 글을 읽게 되었다.

이 글을 보고 이것처럼 hook으로 error, loading 값을 추가해서 return 하는식으로 바꿔주면 이용하는데 간편할거 같아 윗글의 코드에서 Typescript로만 바꿔 만들어 보았다.

 

예제 코드는 kakao의 키워드로 장소찾기 api를 이용하였다.

 

스크롤 내려서 최종부분만 보시길 바랍니다. ㅋㅋㅋㅋ 바보같은 실수를 했네요.


예제 코드

//useAxios hook
import { useState, useEffect } from "react";
import axios, { AxiosRequestConfig } from "axios";

axios.defaults.baseURL = "https://dapi.kakao.com";

type AxiosProps = {
  method: "get" | "post" | "put" | "delete";
  url: string;
  config?: AxiosRequestConfig;
};

const useAxios = ({ method, url, config }: AxiosProps) => {
  const [response, setResponse] = useState(null);
  const [error, setError] = useState("");
  const [loading, setloading] = useState(true);

  const fetchData = () => {
    axios[method](url, config)
      .then((res) => {
        setResponse(res.data);
      })
      .catch((err) => {
        setError(err);
      })
      .finally(() => {
        setloading(false);
      });
  };

  useEffect(() => {
    fetchData();
  }, []);

  return { response, error, loading };
};

export default useAxios;

사용하는 곳에선

//사용하는 컴포넌트에서
const { response, loading, error } = useAxios({
    method: "get",
    url: "/v2/local/search/keyword.json",
    config: {
      headers: {
        Authorization: `KakaoAK ${KAKAO_REST_API_KEY}`,
      },
      params: {
        query: "카페",
        page: currentPage,
        size: size,
      },
    },
  });

추가

생각해보니까 버튼 on click event 때 실행시키거나, refetch할때의 기능이 없어서  axios-hooks의 모듈에서 useAxios를 참고해서 코드 parameter를 추가했다. 그리고 초기 실행을 멈추고 execution을 실행할때 해당 api가 호출되게 하였다.

 

성공 실패일때 callback도 넣어주고 싶다면 execution func의 파라미터를 추가하길 바란다.

import { useState, useEffect } from "react";
import axios, { AxiosRequestConfig } from "axios";

type AxiosProps = {
  method: "get" | "post" | "put" | "delete";
  url: string;
  config?: AxiosRequestConfig;
};

const useAxiosExecution = <T>({
  method,
  url,
  config,
}: AxiosProps): [
  {
    response: T | undefined;
    error: string;
    loading: boolean;
  },
  () => void
] => {
  const [response, setResponse] = useState<T>();
  const [error, setError] = useState("");
  const [loading, setloading] = useState(true);

  const execution = () => {
    setloading(true);
    axios[method](url, config)
      .then((res) => {
        setResponse(res.data);
      })
      .catch((err) => {
        setError(err);
      })
      .finally(() => {
        setloading(false);
      });
  };

  return [{ response, error, loading }, execution];
};

export default useAxiosExecution;

최종

이용하다보니까 엄청 바보같은 실수를 했다는걸 알았다.

그래.. get, delete와 post, put의 parameter는 다른데.. 뭔가 이상하다 했다. 킬킬킬

import { useState, useEffect } from "react";
import axios, { AxiosRequestConfig } from "axios";
import { AnyKindOfDictionary } from "lodash";
import qs from "qs";

type AxiosProps = {
  method: "get" | "post" | "put" | "delete";
  url: string;
  data?: any;
  config?: AxiosRequestConfig;
};

const useAxiosExecution = <T>({
  method,
  url,
  data,
  config,
}: AxiosProps): [
  {
    response: T | undefined;
    error: string;
    loading: boolean;
  },
  () => void
] => {
  const [response, setResponse] = useState<T>();
  const [error, setError] = useState("");
  const [loading, setloading] = useState(true);

  const execution = () => {
    setloading(true);

    if (method === "get" || method == "delete") {
      axios[method](url, config)
        .then((res) => {
          setResponse(res.data);
        })
        .catch((err) => {
          setError(err);
        })
        .finally(() => {
          setloading(false);
        });
    } else {
      axios[method](url, qs.stringify(data), config)
        .then((res) => {
          setResponse(res.data);
        })
        .catch((err) => {
          setError(err);
        })
        .finally(() => {
          setloading(false);
        });
    }
    axios.delete()
  };

  return [{ response, error, loading }, execution];
};

export default useAxiosExecution;

이게 최종이다. 저 if else가 너무 맘에 안들긴 하지만, 일단은 뭐..


결과

결과

npm 모듈에 있는거 쓰는것도 좋아보인다. ㅋㅋㅋ 그래도 모듈들 까보면서 도움은 된듯

반응형
Comments