You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native中如何在非组件内删除Token并跳转至登录页

解决React Native非组件中AccessToken刷新失败后的登出跳转问题

方案一:使用全局Navigation Ref

这是最直接的实现方式,通过创建全局导航引用,让非组件代码也能调用导航方法。

  1. 创建全局导航ref文件
// navigationRef.ts
import React from 'react';
import { NavigationContainerRef, StackActions } from '@react-navigation/native';
import { RootStackParamList } from './path-to-your-types';

export const navigationRef = React.createRef<NavigationContainerRef<RootStackParamList>>();

// 封装导航操作方法
export const popToTop = () => {
  navigationRef.current?.dispatch(StackActions.popToTop());
};

export const navigateToLogin = () => {
  navigationRef.current?.navigate('LoginScreen');
};
  1. 在NavigationContainer中绑定ref
// App.tsx
import { NavigationContainer } from '@react-navigation/native';
import { navigationRef } from './navigationRef';

function App() {
  return (
    <NavigationContainer ref={navigationRef}>
      {/* 你的导航栈结构 */}
    </NavigationContainer>
  );
}
  1. 修改deleteTokens方法,移除navigation参数
import { popToTop } from './navigationRef';

const deleteTokens = async () => {
  await SecureStore.deleteItemAsync('secure_access_token');
  await SecureStore.deleteItemAsync('secure_refresh_token');
  await SecureStore.deleteItemAsync('secure_user_token');
  await SecureStore.deleteItemAsync('secure_deviceid');
  await SecureStore.deleteItemAsync('current_curriculum');
  popToTop(); // 或者直接调用navigateToLogin()跳转到登录页
};
  1. 在Apollo RetryLink中直接调用deleteTokens
const linksFrom = from([
  new RetryLink({
    attempts: async (count, operation, error) => {
      if (count > 1 && error) {
        await deleteTokens();
        return false;
      }
      return refreshLogin()
        .then(() => false)
        .catch(async () => {
          await deleteTokens();
          return false;
        });
    },
  }),
  graphqlAuthLink(),
  uploadLink,
]);

方案二:使用状态管理库(以Zustand为例)

通过状态管理维护登录状态,在根组件监听状态变化执行登出跳转,适合中大型项目的状态统一管理。

  1. 创建登录状态store
// authStore.ts
import { create } from 'zustand';
import * as SecureStore from 'expo-secure-store';

interface AuthState {
  isLoggedIn: boolean;
  logout: () => Promise<void>;
}

export const useAuthStore = create<AuthState>((set) => ({
  isLoggedIn: false,
  logout: async () => {
    // 删除所有token
    await SecureStore.deleteItemAsync('secure_access_token');
    await SecureStore.deleteItemAsync('secure_refresh_token');
    await SecureStore.deleteItemAsync('secure_user_token');
    await SecureStore.deleteItemAsync('secure_deviceid');
    await SecureStore.deleteItemAsync('current_curriculum');
    // 更新登录状态
    set({ isLoggedIn: false });
  },
}));
  1. 在根组件监听登录状态变化
// App.tsx
import { useAuthStore } from './authStore';
import { NavigationContainer } from '@react-navigation/native';
import { useNavigation, StackActions } from '@react-navigation/native';

function AuthListener() {
  const isLoggedIn = useAuthStore((state) => state.isLoggedIn);
  const navigation = useNavigation();

  React.useEffect(() => {
    if (!isLoggedIn) {
      navigation.dispatch(StackActions.popToTop());
      // 或者直接跳转到登录页:navigation.navigate('LoginScreen')
    }
  }, [isLoggedIn, navigation]);

  return null;
}

function App() {
  return (
    <NavigationContainer>
      <AuthListener />
      {/* 你的导航栈 */}
    </NavigationContainer>
  );
}
  1. 在RetryLink中触发登出
import { useAuthStore } from './authStore';

const linksFrom = from([
  new RetryLink({
    attempts: async (count, operation, error) => {
      if (count > 1 && error) {
        await useAuthStore.getState().logout();
        return false;
      }
      return refreshLogin()
        .then(() => false)
        .catch(async () => {
          await useAuthStore.getState().logout();
          return false;
        });
    },
  }),
  graphqlAuthLink(),
  uploadLink,
]);

方案三:使用事件发射器

通过事件触发解耦登出逻辑,适合需要在多个非组件位置触发登出的场景。

  1. 在非组件中触发登出事件
import { DeviceEventEmitter } from 'react-native';

const linksFrom = from([
  new RetryLink({
    attempts: async (count, operation, error) => {
      if (count > 1 && error) {
        DeviceEventEmitter.emit('triggerLogout');
        return false;
      }
      return refreshLogin()
        .then(() => false)
        .catch(() => {
          DeviceEventEmitter.emit('triggerLogout');
          return false;
        });
    },
  }),
  graphqlAuthLink(),
  uploadLink,
]);
  1. 在根组件监听事件并执行登出
// App.tsx
import { DeviceEventEmitter } from 'react-native';
import { useNavigation, StackActions } from '@react-navigation/native';
import * as SecureStore from 'expo-secure-store';

function App() {
  const navigation = useNavigation();

  React.useEffect(() => {
    const logoutListener = DeviceEventEmitter.addListener('triggerLogout', async () => {
      // 删除token
      await SecureStore.deleteItemAsync('secure_access_token');
      await SecureStore.deleteItemAsync('secure_refresh_token');
      await SecureStore.deleteItemAsync('secure_user_token');
      await SecureStore.deleteItemAsync('secure_deviceid');
      await SecureStore.deleteItemAsync('current_curriculum');
      // 跳转登录页
      navigation.dispatch(StackActions.popToTop());
    });

    // 清理监听
    return () => logoutListener.remove();
  }, [navigation]);

  return (
    <NavigationContainer>
      {/* 你的导航栈 */}
    </NavigationContainer>
  );
}

内容的提问来源于stack exchange,提问作者Stephanie Dietrich

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 02:30:54