Exemplo prático Axios Interceptor consumindo várias APIs

Exemplo prático Axios Interceptor consumindo várias APIs

Tags
React Native
Published
April 12, 2024
Author
Matheus Costa
Exemplo prático de como configurar o Axios Interceptor consumindo várias APIs
 
  • Arquivo services/apis.tsx
import axios, { AxiosInstance } from "axios"; type ICustomInstace = AxiosInstance & { defaults: { customBaseURL?: string; }; }; export const instance: ICustomInstace = axios.create({}); export const apiExemplo1 = () => { instance.defaults.baseURL = process.env.EXPO_PUBLIC_API_EXEMPLO1; return instance; }; export const apiExemplo2 = () => { instance.defaults.baseURL = process.env.EXPO_PUBLIC_API_EXEMPLO2; return instance; }; export const apiExemplo3 = () => { instance.defaults.baseURL = process.env.EXPO_PUBLIC_API_EXEMPLO3; return instance; };
 
  • Arquivo services/apis.interceptor.tsx como um componente funcional:
import { useAuth } from "@/hooks/useAuth"; import { useEffect } from "react"; import { apiAuth, instance } from "./apis"; import { storage } from "./storage"; const AxiosInterceptor = ({ children }) => { const { setToken, setRefreshToken, setTokenDecoded, setRefreshTokenDecoded } = useAuth(); const navigation = useNavigation(); useEffect(() => { // Intercepta a requisição (request) instance.interceptors.request.use((request) => { return request; }); // Intercepta a resposta (response) instance.interceptors.response.use( (response) => { return response; }, async (error) => { const originalReq = error.config; if ( error.response.status === 401 && originalReq && !originalReq._retry ) { originalReq._retry = true; const refresh = storage.getString("tokenRefresh"); if (!refresh) { return Promise.reject(error); } const storagedTokenRefresh = storage.getString("tokenRefreshExp"); const currentTime = new Date(); const timeExpiryRefreshToken = new Date(storagedTokenRefresh); // Se o token expirar, navega p/ tela de sessão expirada if (timeExpiryRefreshToken && currentTime >= timeExpiryRefreshToken) { navigation.navigate("SessionExpired"); return Promise.reject(error); } return apiAuth() .get("/tokenrefresh", { headers: { Authorization: refresh }, }) .then(async (responseRefresh) => { const newAccessToken = responseRefresh.data.accesstoken; const newRefreshToken = responseRefresh.data.refreshtoken; const newTokenDecoded = jwtDecode(newAccessToken) as JWTPayload; const newRefreshTokenDecoded = jwtDecode( newRefreshToken, ) as JWTPayloadRefresh; const newTimeExpireJWT = newRefreshTokenDecoded.exp; const newTimeExpire = new Date( newTimeExpireJWT * 1000, ).toString(); storage.set("token", newAccessToken); storage.set("tokenRefresh", newRefreshToken); storage.set("tokenRefreshExp", newTimeExpire); setToken(newAccessToken); setRefreshToken(newRefreshToken); setTokenDecoded(newTokenDecoded); setRefreshTokenDecoded(newRefreshTokenDecoded); originalReq.headers["Authorization"] = newAccessToken; return instance(originalReq); }) .catch((refreshError) => { return Promise.reject(refreshError); }); } else { return Promise.reject(error); } }, ); }, []); return children; }; export default AxiosInterceptor;
  • Envolva o arquivo de entrada do app o com componente AxiosInterceptor:
import * as React from 'react'; export default function App() { return ( <AuthProvider> <AxiosInterceptor> <StatusBarCustom /> <Routes /> </AxiosInterceptor> </AuthProvider> ); }
  • Tela sessão expirada:
... import { BackHandler, View } from "react-native"; import { Button, Text } from "react-native-paper"; export default function SessionExpired({ route }) { const { t } = useTranslation(); const currentRoute = useRoute(); const { setUser, setToken, setRefreshToken, setTokenDecoded, setRefreshTokenDecoded, } = useAuth(); // Limpa dados do storage e direciona pra tela de login async function clearAllSession() { storage.clearAll(); setUser(null); setToken(null); setRefreshToken(null); setTokenDecoded(null); setRefreshTokenDecoded(null); } // Ação botão "voltar" físico Android useFocusEffect( useCallback(() => { const onBackPress = () => { if (route.name === currentRoute.name) { clearAllSession(); return true; } else { return false; } }; BackHandler.addEventListener("hardwareBackPress", onBackPress); return () => BackHandler.removeEventListener("hardwareBackPress", onBackPress); }, [route]), ); return ( <ImgBackground> <Container> <ContainerSurface> <View className="items-center justify-center gap-y-4"> <LottieSessionExpired /> <Text className="font-title text-2xl"> {t("session-expired.title")} </Text> <Text className="font-body"> {t("session-expired.description")} </Text> <Button mode="contained" icon="logout" className="w-[300]" onPress={() => { clearAllSession(); }} > {t("session-expired.button")} </Button> </View> </ContainerSurface> </Container> </ImgBackground> ); }