Update package layout
This commit is contained in:
93
lib/provider/axios/AxiosProvider.tsx
Normal file
93
lib/provider/axios/AxiosProvider.tsx
Normal file
@@ -0,0 +1,93 @@
|
||||
import type { AxiosError, AxiosInstance } from "axios";
|
||||
import axios from "axios";
|
||||
import { createContext, useContext, useMemo } from "react";
|
||||
import { useToken } from "../token";
|
||||
|
||||
|
||||
export interface AxiosState {
|
||||
publicApi: AxiosInstance;
|
||||
authorizedApi: AxiosInstance;
|
||||
}
|
||||
|
||||
const initialState: AxiosState = {
|
||||
publicApi: {} as AxiosInstance,
|
||||
authorizedApi: {} as AxiosInstance
|
||||
}
|
||||
|
||||
const AxiosContext = createContext<AxiosState>(initialState);
|
||||
|
||||
|
||||
export default function AxiosProvider({
|
||||
apiUrl,
|
||||
children
|
||||
}: Readonly<{
|
||||
apiUrl: string;
|
||||
children: React.ReactNode;
|
||||
}>){
|
||||
const { getToken } = useToken();
|
||||
|
||||
const publicApi = useMemo(() => {
|
||||
const api = axios.create({
|
||||
baseURL: apiUrl
|
||||
});
|
||||
return api;
|
||||
}, [apiUrl]);
|
||||
const authorizedApi = useMemo(() => {
|
||||
const api = axios.create({
|
||||
baseURL: apiUrl
|
||||
});
|
||||
api.interceptors.request.use(async (config) => {
|
||||
try{
|
||||
const token = await getToken();
|
||||
if(token){
|
||||
config.headers.Authorization = `Bearer ${token}`;
|
||||
}
|
||||
return config;
|
||||
}
|
||||
catch(error){
|
||||
return Promise.reject(error as Error);
|
||||
}
|
||||
});
|
||||
api.interceptors.response.use(r => r, async (error: AxiosError) => {
|
||||
const original = error.config;
|
||||
if(!original){
|
||||
return Promise.reject(error);
|
||||
}
|
||||
if(error.response?.status === 401 && !original._retry){
|
||||
original._retry = true;
|
||||
try{
|
||||
const newToken = await getToken();
|
||||
original.headers.Authorization = `Bearer ${newToken}`;
|
||||
return api(original);
|
||||
}
|
||||
catch(refreshError){
|
||||
return Promise.reject(refreshError as Error);
|
||||
}
|
||||
}
|
||||
});
|
||||
return api;
|
||||
}, [apiUrl, getToken]);
|
||||
|
||||
const value = useMemo(() => ({
|
||||
publicApi,
|
||||
authorizedApi
|
||||
}), [authorizedApi, publicApi]);
|
||||
|
||||
return (
|
||||
<AxiosContext.Provider value={value}>
|
||||
{children}
|
||||
</AxiosContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// eslint-disable-next-line react-refresh/only-export-components
|
||||
export function useAxios(){
|
||||
const context = useContext(AxiosContext);
|
||||
|
||||
if(!context){
|
||||
throw new Error("useAxios must be called inside an AxiosProvider");
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
Reference in New Issue
Block a user