React Native Expo中Axios拦截器401状态无法跳转登录页求助
问题分析
你代码里的核心问题是在axios拦截器中直接调用useNavigation()——React Hooks只能在函数组件的顶层或自定义Hook中使用,拦截器属于普通异步函数,不符合Hook的使用规则,导致获取的navigation对象无效,无法触发页面跳转。
解决方案
我们可以通过导航容器的Ref来获取全局可用的navigation对象,具体步骤如下:
1. 在根组件中创建并导出导航Ref
在你的App.js(或导航根组件)中,创建一个navigationRef并关联到NavigationContainer:
import { NavigationContainer, useNavigationContainerRef } from '@react-navigation/native'; import { createNativeStackNavigator } from '@react-navigation/native-stack'; // 创建并导出导航Ref export const navigationRef = useNavigationContainerRef(); function App() { const Stack = createNativeStackNavigator(); return ( <NavigationContainer ref={navigationRef}> <Stack.Navigator initialRouteName="Home"> {/* 你的页面路由配置,比如SignIn页面 */} <Stack.Screen name="SignIn" component={SignInScreen} /> {/* 其他页面 */} </Stack.Navigator> </NavigationContainer> ); } export default App;
2. 修改axios拦截器,使用导航Ref跳转
修改你的api封装文件,导入刚才的navigationRef,替换原来的useNavigation调用:
import axios from "axios"; import { BASE_URL } from '@env'; import * as SecureStore from 'expo-secure-store'; import { navigationRef } from './App'; // 导入导航Ref const TOKEN_KEY = "token"; const api = axios.create({ baseURL: BASE_URL }); api.interceptors.response.use( (response) => response, async (error) => { // 先判断error.response是否存在,避免网络错误导致报错 if (error.response?.status === 401 || error.response?.status === 500) { // 清空授权头 api.defaults.headers.common['Authorization'] = ''; // 删除本地存储的token await SecureStore.deleteItemAsync(TOKEN_KEY); // 确保导航容器已初始化后再跳转 if (navigationRef.isReady()) { navigationRef.navigate('SignIn'); } } return Promise.reject(error); } ); export { api };
额外注意事项
- 用
error.response?.status的可选链操作符,避免网络请求失败(无response对象)时抛出错误; - 调用
navigationRef.navigate前先通过isReady()判断导航容器是否已挂载,防止在应用初始化阶段调用跳转导致报错。
内容的提问来源于stack exchange,提问作者Maulana Irfan Firdian
相关产品推荐
相关产品推荐

