web
Axios Interceptor에서 hook 사용하기
Jaaaay
2023. 1. 24. 15:56
요구사항: API 요청에서 header에 hash key를 담아 보내야 하는 상황에서 URL에 있는 키 정보를 next/router를 통해 추출해 사용하고자 했음. 기존 Axios client 파일에서는 hook을 사용할 수 없어 해결방안을 모색.
구글링을 통해 본 대부분의 경우는 header에 key를 담는 경우에 대해서 local storage 값을 사용하고 있었다.
이를 해결하기 위해서 <APP/> 자체를 감싸줄 수 있는 훅을 생성했다.
// axiosInterceptor.tsx
import axios, { AxiosResponse } from 'axios';
import React, { useState, useEffect } from 'react';
import { useRouter } from 'next/router';
import { apiAddress, env } from '../config';
const api = axios.create({ baseURL: apiAddress[env], withCredentials: true });
const AxiosInterceptor = ({ children }: { children: React.ReactElement }) => {
const [isSet, setIsSet] = useState(false);
const router = useRouter();
useEffect(() => {
let { id } = router.query;
if (Array.isArray(id) && id.length !== 0) {
id = id.join('/') as string;
console.log(id);
}
api.interceptors.request.use(
(config) => {
config.headers = {
ANONYMOUS_KEY: id as string,
};
return config;
},
(error) => {
console.log(error);
return error;
}
);
const interceptor = api.interceptors.response.use(
(response: AxiosResponse) => {
console.log(response);
return response;
},
(error: unknown) => {
return Promise.reject(error);
// return toErrorWithMessage(error);
}
);
if (id) {
setIsSet(true);
}
return () => {
api.interceptors.response.eject(interceptor);
api.interceptors.request.eject(interceptor);
};
}, [router]);
if (isSet) {
return children;
} else {
return null;
}
};
export default api;
export { AxiosInterceptor };
// _app.tsx
import type { AppProps } from 'next/app';
import { QueryClient, QueryClientProvider } from 'react-query';
import { RecoilRoot } from 'recoil';
import { AxiosInterceptor } from '../hooks/axiosInterceptor';
const queryClient = new QueryClient();
export default function App({ Component, pageProps }: AppProps) {
return (
<AxiosInterceptor>
<RecoilRoot>
<QueryClientProvider client={queryClient}>
<Component {...pageProps} />
</QueryClientProvider>
</RecoilRoot>
</AxiosInterceptor>
);
}
useRouter()를 정상적으로 이용할 수 있었다.
Note : you must remove interceptors in useEffect return statement, because every execution of useEffect, adds a new interceptor to Axios instance.
axios 인스턴스가 useEffect마다 생성되기 때문에 리턴 문에서 제거해 줄 필요가 있다.
단점
hook 동작 전에 렌더링이 된다던지 하는 문제를 줄이기 위해 set state를 통해 hook 동작 전 렌더링을 방지해주었다. (원글의 댓글 참고)
~
예전에 필요에 의해 적용하고 지금까지 잘 사용하고 있다. 우려와는 달리 문제도 없었고 리액트 컴포넌트를 사용하듯이 이런저런 값을 편한대로 쓸 수 있어 아주 만족하며 사용하는 중...
참고: https://dev.to/arianhamdi/react-hooks-in-axios-interceptors-3e1h