You need to enable JavaScript to run this app. React Native结合Apollo Client实现已登录用户从缓存加载数据的方法
优惠活动
大模型
产品
解决方案
定价
更多

React Native结合Apollo Client实现已登录用户从缓存加载数据的方法

React Native + Apollo Client 登录持久化与缓存优先加载实现方案

核心问题根因

  • 当前Apollo缓存仅存储在内存中,应用关闭后缓存即被清空,重开应用必然会触发网络请求
  • 登录态判断逻辑不合理:Routes组件直接读取本地存储的token即标记为已登录,未做有效性校验
  • 缺少明确的缓存读取策略配置,容易触发不必要的网络请求

分步实现方案

1. 配置Apollo持久化缓存(解决重开应用缓存丢失问题)

  • 引入apollo3-cache-persist配合AsyncStorage,将Apollo内存缓存持久化到本地存储
  • 初始化Apollo Client时关联持久化的缓存实例,同时配置全局默认查询策略为cache-first

初始化代码示例(新建apollo.js作为客户端配置文件):

import { ApolloClient, InMemoryCache } from '@apollo/client';
import { persistCache } from 'apollo3-cache-persist';
import AsyncStorage from '@react-native-async-storage/async-storage';

// 创建缓存实例
const cache = new InMemoryCache();

// 配置缓存持久化,写入AsyncStorage
persistCache({
  cache,
  storage: AsyncStorage,
});

// 初始化全局Apollo Client
export const apolloClient = new ApolloClient({
  uri: '你的GraphQL接口地址',
  cache,
  // 全局默认配置优先读缓存
  defaultOptions: {
    watchQuery: {
      fetchPolicy: 'cache-first',
    },
    query: {
      fetchPolicy: 'cache-first',
    },
  },
});

2. 重构登录态初始化逻辑(解决自动登录校验问题)

  • 将本地token读取、有效性校验的逻辑统一放到AuthProvider中,Routes组件仅根据AuthProvider返回的user状态渲染对应页面
  • 启动应用时优先读取本地存储的用户凭证,携带凭证向服务端发起登录校验请求,校验通过再标记为已登录
  • 退出登录时同时清空本地存储和Apollo缓存,避免多账号切换时的数据串读

AuthProvider关键逻辑修改:

export default function AuthProvider({children}) {
  const [callData, {loading, data}] = useLazyQuery(AUTH_USER);
  const [user, setUser] = useState(null);
  const [info, setInfo] = useState(null);
  // 增加初始化完成标识,避免页面闪烁
  const [isInitComplete, setIsInitComplete] = useState(false);

  // 启动时自动读取本地存储做登录校验
  useEffect(() => {
    const initAuth = async () => {
      try {
        const storedUser = await AsyncStorage.getItem('user');
        if (storedUser) {
          const userInfo = JSON.parse(storedUser);
          setInfo(userInfo);
          // 登录校验必须走网络,不能读缓存
          await callData({
            variables: {name: userInfo.name, key: userInfo.key},
            fetchPolicy: 'network-only',
          });
        }
      } catch (err) {
        console.log('登录态初始化失败', err);
        await resetStorage();
      } finally {
        setIsInitComplete(true);
      }
    };
    initAuth();
  }, []);

  // 校验结果处理逻辑保留原有逻辑
  useEffect(() => {
    if (data) {
      if (data.UserAuth.AuthStatus) {
        setUser(true);
      } else {
        resetStorage();
        setUser(false);
      }
    }
  }, [data]);

  // 启动阶段未完成初始化时显示加载态
  if (loading || !isInitComplete) {
    return (
      <Center>
        <ActivityIndicator size="large" color="#0000ff" />
      </Center>
    );
  }

  return (
    <MyContext.Provider
      value={{
        user,
        info,
        LogIn: async (name, passw) => {
          // 原有登录逻辑保留
        },
        LogOut: async () => {
          setUser(null);
          setInfo(null);
          await AsyncStorage.removeItem('user');
          // 退出登录时清空全量Apollo缓存
          await apolloClient.clear();
        },
      }}>
      {children}
    </MyContext.Provider>
  );
}

Routes组件简化逻辑(移除原有的本地存储读取,统一由AuthProvider处理):

export default function Routes() {
  const {user} = useContext(MyContext);
  return <>{user ? <AppTabs /> : <AuthTabs />}</>;
}

3. 配置AppTabs的缓存优先读取规则

  • 全局默认启用cache-first策略:优先读取本地缓存的查询数据,仅当缓存不存在时才发起网络请求
  • 等待用户信息(请求变量)加载完成后再发起业务查询,避免空变量导致的无效请求
  • 移除手动调用client.readQuery的冗余逻辑,useQuery会自动按照配置的策略读取缓存

AppTabs关键逻辑修改:

export default function AppTabs() {
  const {info} = useContext(MyContext);
  const {loading, error, data} = useQuery(GET_USER, {
    variables: info,
    fetchPolicy: 'cache-first', // 显式指定优先读缓存
    skip: !info, // 变量未加载完成时跳过请求
  });

  if (loading || !data) {
    return (
      <Center>
        <ActivityIndicator size="large" color="#0000ff" />
      </Center>
    );
  }
  // 原有业务逻辑保留
}

注意事项

  • 缓存匹配规则:只有当查询的GraphQL文档、请求变量和之前写入缓存时完全一致时,才会命中缓存
  • 登录校验特殊规则:校验接口的fetchPolicy必须设置为network-only,不能走缓存,避免token过期后仍被判定为登录有效
  • 缓存清理规则:退出登录、用户权限变更时需要主动调用apolloClient.clear()清空全量缓存

内容的提问来源于stack exchange,提问作者Petr Špác

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.09 11:24:04