Apollo GraphQL:如何从缓存获取Mutation写入的数据?
嘿,针对你在React Native应用里处理GraphQL Mutation返回数据缓存的需求,我整理了两种实用方案,你可以根据自己的技术栈来选~
如果你的项目用了Apollo Client这类专业GraphQL客户端,它自带缓存管理能力,只需要做一点配置就能让Mutation返回的用户信息自动进入缓存,方便后续根查询读取。
第一步:确保Mutation返回完整的用户字段
先让你的登录/认证Mutation返回需要的用户信息,比如:mutation Login($credentials: CredentialsInput!) { login(credentials: $credentials) { token user { id name email avatar } } }第二步:在Mutation中手动更新缓存
Apollo Client默认不会自动把Mutation结果同步到查询缓存里,所以需要用update函数把返回的用户数据写入缓存,和你的根查询结构匹配:import { gql, useMutation } from '@apollo/client'; import AsyncStorage from '@react-native-async-storage/async-storage'; // 定义登录Mutation和用户查询 const LOGIN_MUTATION = gql` mutation Login($credentials: CredentialsInput!) { login(credentials: $credentials) { token user { id name email } } } `; const GET_USER_QUERY = gql` query GetCurrentUser { user { id name email } } `; function LoginScreen() { const [login] = useMutation(LOGIN_MUTATION, { update(cache, { data: { login } }) { // 将返回的user数据写入缓存,匹配根查询的结构 cache.writeQuery({ query: GET_USER_QUERY, data: { user: login.user }, }); // 同时把token存入AsyncStorage AsyncStorage.setItem('authToken', login.token); }, }); const handleLogin = async (email, password) => { try { await login({ variables: { credentials: { email, password } } }); // 登录成功后跳转首页等逻辑 } catch (err) { console.error('登录失败:', err); } }; // 登录UI代码... }第三步:从缓存读取用户信息
之后用useQuery调用根查询时,Apollo会直接从缓存取数据,不用重复发请求:import { useQuery } from '@apollo/client'; import { ActivityIndicator, View, Text } from 'react-native'; function HomeScreen() { const { data, loading } = useQuery(GET_USER_QUERY); if (loading) return <ActivityIndicator />; return ( <View> <Text>欢迎回来,{data.user.name}!</Text> </View> ); }
另外,记得初始化Apollo Client时把AsyncStorage里的token加到请求头,保证后续请求带认证信息:
import { ApolloClient, InMemoryCache, createHttpLink } from '@apollo/client'; import { setContext } from '@apollo/client/link/context'; import AsyncStorage from '@react-native-async-storage/async-storage'; const httpLink = createHttpLink({ uri: '你的GraphQL服务端地址', }); const authLink = setContext(async (_, { headers }) => { const token = await AsyncStorage.getItem('authToken'); return { headers: { ...headers, authorization: token ? `Bearer ${token}` : '', }, }; }); const client = new ApolloClient({ link: authLink.concat(httpLink), cache: new InMemoryCache(), });
如果没用到GraphQL客户端,自己用fetch或axios发请求的话,就需要手动管理缓存,比如用AsyncStorage或者全局状态(Context/Redux)。
第一步:发送Mutation并保存数据
发送POST请求到GraphQL端点,拿到token和用户信息后,分别存入AsyncStorage:import AsyncStorage from '@react-native-async-storage/async-storage'; import axios from 'axios'; const handleLogin = async (email, password) => { try { const response = await axios.post('你的GraphQL服务端地址', { query: ` mutation Login($credentials: CredentialsInput!) { login(credentials: $credentials) { token user { id name email } } } `, variables: { credentials: { email, password } }, }); const { token, user } = response.data.data.login; // 存token await AsyncStorage.setItem('authToken', token); // 存用户信息到缓存 await AsyncStorage.setItem('currentUser', JSON.stringify(user)); } catch (err) { console.error('登录失败:', err); } };第二步:从缓存读取用户信息
用Context来管理用户状态会更方便,避免重复读取AsyncStorage:import { createContext, useContext, useEffect, useState } from 'react'; import AsyncStorage from '@react-native-async-storage/async-storage'; import { ActivityIndicator, View, Text } from 'react-native'; const UserContext = createContext(); export function UserProvider({ children }) { const [user, setUser] = useState(null); useEffect(() => { const loadStoredUser = async () => { const storedUser = await AsyncStorage.getItem('currentUser'); if (storedUser) setUser(JSON.parse(storedUser)); }; loadStoredUser(); }, []); return ( <UserContext.Provider value={{ user, setUser }}> {children} </UserContext.Provider> ); } // 在组件中使用 function HomeScreen() { const { user } = useContext(UserContext); if (!user) return <ActivityIndicator />; return ( <View> <Text>欢迎回来,{user.name}!</Text> </View> ); }
小提醒
不管用哪种方案,当用户修改个人信息时,记得同步更新缓存/状态,保证数据一致性哦~
内容的提问来源于stack exchange,提问作者ozer

