[React] useAxios, axios instance

이해용·2023년 4월 18일
1
post-thumbnail
post-custom-banner

useAxios

재사용 가능한 custom hooks

React 애플리케이션은 구성 요소에서 빌드됩니다. 기본 제공이든 사용자 지정이든 관계없이 구성 요소는 Hooks에서 빌드됩니다. 다른 사람이 만든 사용자 정의 Hook을 자주 사용하겠지만 가끔 직접 작성할 수도 있습니다.

다음 명명 규칙을 따라야 합니다.

  1. React 컴포넌트 이름은 StatusBarSaveButton 같이 대문자로 시작해야 합니다. React 구성 요소는 또한 JSX 조각과 같이 React가 표시하는 방법을 알고 있는 것을 반환해야 합니다.

  2. Hook 이름은 useState(built-in) 또는 useOnlineStatus (custom, like earlier on the page)와 같이 use 다음에 대문자로 시작해야 합니다. Hooks는 임의의 값을 반환할 수 있습니다.

axios instance

useAxios를 사용 하기 전 axios instance를 설정한다면 백엔드와 통신 시 반복되는 작업을 줄일 수 있습니다.(ex. access token 전달, withCredentials: true 등등)

사용자 지정 config로 새로운 Axios 인스턴스를 만들수 있습니다.

axios.create([config])

config 설정은 공식문서에서 확인 가능합니다.

const instance = axios.create({
  baseURL: 'https://some-domain.com/api/',
  timeout: 1000,
  headers: {'X-Custom-Header': 'foobar'}
});

예시

// src/lib/api/index.ts   

import axios from "axios";
import { store } from "../../app/store";

export const axiosInstance = axios.create({
  baseURL: "https://some-domain.com/api/",
  timeout: 60000,
  headers: {'X-Custom-Header': 'foobar'},
  withCredentials: true,
});

axiosInstance.interceptors.request.use(
  (config) => {
    const accessToken = store.getState().accessTokenValue.accessTokenValue;
    // console.log(accessToken);
    if (accessToken) {
      config.headers["Authorization"] = accessToken;
    }
    	console.log("axios config : ", config);
    return config;
  },

  (error) => {
    	console.log("axios config : ", error);
    return Promise.reject(error);
  }
);


axiosInstance.interceptors.response.use(
  (response) => {
    	console.log("axios config : ", response);
    return response;
  },

  (error) => {
    	// 이 부분에서 access token, refresh token 갱신 가능합니다.
    	console.log("axios config : ", error);
    return Promise.reject(error);
  }
);

useAxios 예시

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

import { axiosInstance } from "../../lib/api/index";

export const useAxios = <D = any>(axiosParams: AxiosRequestConfig<D>) => {
  const [response, setResponse] = useState<AxiosResponse | null | any>(null);
  const [error, setError] = useState<AxiosError | any | unknown>(null);
  const [loading, setLoading] = useState(true);
  const [trigger, setTrigger] = useState(0);
  const controllerRef = useRef(new AbortController());

  const refetch = () => {
    setResponse([...response]);
    setError(error);
    setLoading(true);
    setTrigger(Date.now());
  };

  const axiosData = async (params: AxiosRequestConfig<D>) => {
    try {
      const result = await axiosInstance.request({
        ...params,
        signal: controllerRef.current.signal,
      });
      setResponse(result?.data?.data);
    } catch (error: AxiosError | any | unknown) {
      setError(error);
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    axiosData(axiosParams);
  }, [trigger]);

  return {
    response,
    error,
    loading,
    setResponse,
    refetch,
  };
};
// App.tsx

const App () => {
  const {response, error, loading, refetch} = useAxios({
    url: "https://some-domain.com/api/",
    method: "GET", // 생략 가능\
  })
  
  return (
	<div>
      <button type="button" onClick={refetch} />
      {loading ? (
        <div>loading...</div>
      ) : error ? (
        <div>error</div>
      ) : (
        <div>{response}</div>
      )}
    </div>

reference
리액트 공식문서
axios 공식문서
https://blog.sreejit.dev/custom-axios-hook-useaxios-in-typescript-react
https://medium.com/stackanatomy/integrating-axios-with-react-hooks-f3caccee83b3

profile
프론트엔드 개발자입니다.
post-custom-banner

0개의 댓글