Reputation: 1
Hello can anyone help me, I have a problem about axios intercepotrs. When Error Status === 401 My Application (React Native) does not redirect to the signin page.
import axios from "axios";
import {BASE_URL} from '@env'
import { useNavigation } from "@react-navigation/native";
import * as SecureStore from 'expo-secure-store';
const TOKEN_KEY = "token"
const api = axios.create({
baseURL: BASE_URL
})
api.interceptors.response.use(async (response) => {
return response
}, async function (error) {
const navigation = useNavigation()
if (error.response.status === 401 || error.response.status === 500) {
api.defaults.headers.common['Authorization'] = ''
await SecureStore.deleteItemAsync(TOKEN_KEY)
navigation.navigate('SignIn')
}
return Promise.reject(error);
});
export {api}
Can anyone tell me how properly deal with the condition ?
Upvotes: 0
Views: 671
Reputation: 21
If you encounter the issue of needing React hooks e.g. usePathname()
in Axios interceptors but run into React’s rules of hooks error, you can resolve it by creating a React component. This approach leverages React states, effects, and hooks correctly while integrating them with Axios interceptors.
Below is an example of how to achieve this by wrapping your Axios interceptor in a React component:
import { PropsWithChildren, useEffect } from "react";
import { router, usePathname } from "expo-router";
import { useNotification } from "@/components/ui/notification";
import { api } from "./api";
export const AxiosInterceptor = ({ children }: PropsWithChildren) => {
const route = usePathname();
const unguardedRoutes = ["/login", "/register"];
const isGuardedRoute = !unguardedRoutes.includes(route);
useEffect(() => {
/* ======================================== SUCCESS RESPONSE INTERCEPTOR */
const responseInterceptor = (response: any) => {
return response.data;
};
/* ======================================== ERROR RESPONSE INTERCEPTOR */
const errorInterceptor = (e: any) => {
/* ======================================== REDIRECT */
const status = e.response?.status;
const unauthenticatedStatus = [401, 403, 409];
const isUnauthenticated = unauthenticatedStatus.includes(status);
if (isGuardedRoute && isUnauthenticated) {
router.replace("/login");
}
/* ======================================== RETURNS */
return Promise.reject(e);
};
const interceptor = api.interceptors.response.use(responseInterceptor, errorInterceptor);
return () => {
api.interceptors.response.eject(interceptor);
};
}, [isGuardedRoute]);
return children;
};
Wrap your root layout in the AxiosInterceptor
component:
import { AxiosInterceptor } from "./AxiosInterceptor";
const RootLayout = () => {
return (
<AxiosInterceptor>
<Stack>
<Stack.Screen name="(tabs)" />
<Stack.Screen name="(auth)" />
<Stack.Screen name="+not-found" />
</Stack>
</AxiosInterceptor>
);
}
Upvotes: 0
Reputation: 1238
You're using useNavigation
, which is a hook, inside a function which is not a React component.
You can transform this into a custom hook or just use the interceptor inside your root (App.js) React component.
Upvotes: 0