Javascript Apollo是否缓存突变返回的数据
我在React应用程序中使用Apollo客户端,我需要进行变异,然后保留返回的数据供以后使用(但我无法访问变量),我是否必须使用其他状态管理解决方案,或者我们可以在Apollo中执行此操作 我读过关于用查询而不是变异来实现这一点的文章 这是到目前为止我的代码Javascript Apollo是否缓存突变返回的数据,javascript,reactjs,graphql,react-apollo,apollo-client,Javascript,Reactjs,Graphql,React Apollo,Apollo Client,我在React应用程序中使用Apollo客户端,我需要进行变异,然后保留返回的数据供以后使用(但我无法访问变量),我是否必须使用其他状态管理解决方案,或者我们可以在Apollo中执行此操作 我读过关于用查询而不是变异来实现这一点的文章 这是到目前为止我的代码 // Mutation const [myMutation, { data, errors, loading }] = useMutation(MY_MUTATION, { onCompleted({ myMutation }) {
// Mutation
const [myMutation, { data, errors, loading }] = useMutation(MY_MUTATION, {
onCompleted({ myMutation }) {
console.log('myMutation: ', myMutation.dataToKeep);
if (myMutation && myMutation.dataToKeep)
SetResponse(myMutation.dataToKeep);
},
onError(error) {
console.error('error: ', error);
},
});
//How I call it
onClick={() => {
myMutation({
variables: {
input: {
phoneNumber: '0000000000',
id: '0000',
},
},
});
}}
编辑:
这是突变
export const MY_MUTATION = gql`
mutation MyMutation($input: MyMutationInput!) {
myMutation(input: $input) {
dataToKeep
expiresAt
}
}
`;
以及这种突变的模式
MyMutationInput:
phoneNumber: String!
id: String!
MyMutationPayload:
dataToKeep
expiresAt
案例1:有效负载正在使用公共实体
简单地说,Apollo客户端的缓存保留了从查询和突变中接收到的所有内容,尽管模式需要包含id:id代码>字段和任何查询都需要使用相关节点上的id
和\uuuu typename
字段,以便客户端知道要更新缓存的哪个部分
这假设变异负载是来自模式的公共数据,可以通过正常查询检索。这是最好的情况
给定服务器上的以下架构:
type User {
id: ID!
phoneNumber: String!
}
type Query {
user(id: String!): User!
}
type UpdateUserPayload {
user: User!
}
type Mutation {
updateUser(id: String!, phoneNumber: String!): UpdateUserPayload!
}
假设:
响应中包含的每个可识别对象的缓存
缓存按ID将对象存储在平面查找表中
每当传入对象以与现有对象相同的ID存储时,这些对象的字段就会合并
- 如果传入对象和现有对象共享任何字段,则传入对象将覆盖这些字段的缓存值
- 仅出现在现有对象或仅出现在传入对象中的字段将被保留
规范化在数据库上构造数据图的部分副本
客户端,其格式针对读取和更新
在应用程序更改状态时绘制图形
客户的突变应该是
mutation UpdateUserPhone($phoneNumber: String!, $id: String!) {
updateUser(id: $id, phoneNumber: $phoneNumber) {
user {
__typename # Added by default by the Apollo client
id # Required to identify the user in the cache
phoneNumber # Field that'll be updated in the cache
}
}
}
然后,通过应用程序中相同的Apollo客户端使用此用户的任何组件都将自动更新。没有什么特别的事情要做,客户机将默认使用缓存,并在数据更改时触发渲染
从'@apollo/client'导入{gql,useQuery};
const USER_QUERY=gql`
查询GetUser($id:String!){
用户(id:$id){
__字体名
身份证件
电话号码
}
}
`;
const UserComponent=({userId})=>{
const{loading,error,data}=useQuery(用户查询{
变量:{id:userId},
});
if(加载)返回null;
if(error)返回`error!${error}`;
返回{data.user.phoneNumber};
}
默认设置为先缓存
案例2:负载是特定于突变的自定义数据
如果该数据实际上在模式的其他地方不可用,那么就不可能像上面解释的那样自动使用Apollo缓存
使用其他状态管理解决方案
有两种选择:
- 本地存储
- 等等
下面是一个使用localStorage
的示例:
const[login,{loading,error}]=useCommutation(login\u USER{
未完成({login}){
localStorage.setItem('token',login.token);
setItem('userId',login.id);
}
});
这是一个纯Apollo GraphQL解决方案,因为客户端也是一个状态管理库,它支持有用的开发人员工具,并有助于对数据进行推理
创建本地模式
// schema.js
export const typeDefs = gql`
type DataToKeep {
# anything here
}
extend type Query {
dataToKeep: DataToKeep # probably nullable?
}
`;
初始化自定义缓存
// cache.js
export const dataToKeepVar = makeVar(null);
export const cache = new InMemoryCache({
typePolicies: {
Query: {
fields: {
dataToKeep: {
read() {
return dataToKeepVar();
}
},
}
}
}
});
在客户端初始化时应用架构覆盖
import { InMemoryCache, Reference, makeVar } from '@apollo/client';
import { cache } from './cache';
import { typeDefs } from './schema';
const client = new ApolloClient({
cache,
typeDefs,
// other options like, headers, uri, etc.
});
跟踪突变的变化:
const [myMutation, { data, errors, loading }] = useMutation(MY_MUTATION, {
onCompleted({ myMutation }) {
if (myMutation && myMutation.dataToKeep)
dataToKeepVar(myMutation.dataToKeep);
}
});
然后,查询@client
字段
import { gql, useQuery } from '@apollo/client';
const DATA_QUERY = gql`
query dataToKeep {
dataToKeep @client {
# anything here
}
}
`;
const AnyComponent = ({ userId }) => {
const { loading, error, data } = useQuery(DATA_QUERY);
if (loading) return null;
if (error) return `Error! ${error}`;
return <div>{JSON.stringify(data.dataToKeep)}</div>;
}
从'@apollo/client'导入{gql,useQuery};
const DATA_QUERY=gql`
查询datatokep{
dataToKeep@client{
#这里有什么吗
}
}
`;
const AnyComponent=({userId})=>{
const{loading,error,data}=useQuery(数据查询);
if(加载)返回null;
if(error)返回`error!${error}`;
返回{JSON.stringify(data.dataToKeep)};
}
另请参阅有关的文档。您使用的是哪一版本的apollo客户端?你说的以后使用是什么意思?你的意思是像一个全局状态保存在应用程序中,或者更像一个需要在不同组件之间共享的状态?@ManuelPamplona我使用的是3.2.9“那么,通过应用程序中相同的Apollo客户端使用此用户的任何组件都将自动更新。”我如何在缓存中访问此用户?@Mel无需特别说明,我添加了一个默认情况下使用缓存的简单示例。当我按照您的示例创建新查询时,我会收到“消息”:“字段“myMutation”不存在于“query”类型上,因为API中没有此名称的查询。我遗漏了什么?@Mel好的,在挖掘了一点之后,我加入了另外两个解决方案:使用另一个状态管理解决方案,就像你建议的,以及使用一个本地状态,因为Apollo客户端库也是一个状态管理库。我最终使用了上下文,但你的答案正是我一开始想要做的,谢谢
import { gql, useQuery } from '@apollo/client';
const DATA_QUERY = gql`
query dataToKeep {
dataToKeep @client {
# anything here
}
}
`;
const AnyComponent = ({ userId }) => {
const { loading, error, data } = useQuery(DATA_QUERY);
if (loading) return null;
if (error) return `Error! ${error}`;
return <div>{JSON.stringify(data.dataToKeep)}</div>;
}