Apollo GraphQL 合并缓存数据
Apollo GraphQL merge cached data
我有一个包含 2 个组件的页面,每个组件都有自己的数据请求
例如
<MovieInfo movieId={queryParamsId}/>
const GET_MOVIE_INFO = `gql
query($id: String!){
movie(id: $id){
name
description
}
}`
下一个组件
<MovieActors movieId={queryParamsId}/>
const GET_MOVIE_ACTORS = `gql
query($id: String!){
movie(id: $id){
actors
}
}`
对于这些查询中的每一个,我都使用 apollo hook
const { 数据、加载、错误} = useQuery(GET_DATA, {变量: {id: queryParamsId}}))
一切正常,但我收到一条警告消息:
Cache data may be lost when replacing the movie field of a Query object.
To address this problem (which is not a bug in Apollo Client), either ensure all objects of type Movie have IDs, or define a custom merge function for the Query.movie field, so InMemoryCache can safely merge these objects: { ... }
在 google chrome 上工作正常,但此错误会影响 Safari 浏览器。一切都令人崩溃。我 100% 确定这是因为这条警告消息。在第一个请求中,我在缓存中设置了电影数据,在对同一查询的第二次请求中,我只是用新数据替换旧数据,因此以前缓存的数据是未定义的。我该如何解决这个问题?
已解决!
cache: new InMemoryCache({
typePolicies: {
Query: {
fields: {
YOUR_FIELD: {
merge(existing = [], incoming: any) {
return { ...existing, ...incoming };
// this part of code is depends what you actually need to do, in my
case i had to save my incoming data as single object in cache
}
}
}
}
}
})
});
数据值与我们的架构不一致也有同样的问题。实体中的值类型缺少 id 值。 由不完整的数据迁移引起。
临时解决方案:
const typePolicies = {
PROBLEM_TYPE: {
keyFields: false as false,
},
PARENT_TYPE: {
fields: {
PROBLEM_FIELD: {
merge: true
}
}
}
}
这是 Thomas 提到的相同解决方案,但更短一些
const cache = new InMemoryCache({
typePolicies: {
Query: {
fields: {
YOUR_FIELD: {
// shorthand
merge: true,
},
},
},
},
});
这个和下面的一样
const cache = new InMemoryCache({
typePolicies: {
Query: {
fields: {
YOUR_FIELD: {
merge(existing, incoming, { mergeObjects }) {
return mergeObjects(existing, incoming);
},
},
},
},
},
});
其他答案仍然有效,但从 Apollo Client >= 3.3 开始,有一个 easier option 不需要指定特定字段或自定义合并函数。相反,您只需指定类型,它将合并该类型的所有字段:
const cache = new InMemoryCache({
typePolicies: {
YOUR_TYPE_NAME: {
merge: true,
}
}
});
根据您的示例查询,我猜 id
字段应该可用?尝试在查询中请求 ID,这应该可以更理想地解决问题。
我有一个包含 2 个组件的页面,每个组件都有自己的数据请求 例如
<MovieInfo movieId={queryParamsId}/>
const GET_MOVIE_INFO = `gql
query($id: String!){
movie(id: $id){
name
description
}
}`
下一个组件
<MovieActors movieId={queryParamsId}/>
const GET_MOVIE_ACTORS = `gql
query($id: String!){
movie(id: $id){
actors
}
}`
对于这些查询中的每一个,我都使用 apollo hook
const { 数据、加载、错误} = useQuery(GET_DATA, {变量: {id: queryParamsId}}))
一切正常,但我收到一条警告消息:
Cache data may be lost when replacing the movie field of a Query object. To address this problem (which is not a bug in Apollo Client), either ensure all objects of type Movie have IDs, or define a custom merge function for the Query.movie field, so InMemoryCache can safely merge these objects: { ... }
在 google chrome 上工作正常,但此错误会影响 Safari 浏览器。一切都令人崩溃。我 100% 确定这是因为这条警告消息。在第一个请求中,我在缓存中设置了电影数据,在对同一查询的第二次请求中,我只是用新数据替换旧数据,因此以前缓存的数据是未定义的。我该如何解决这个问题?
已解决!
cache: new InMemoryCache({
typePolicies: {
Query: {
fields: {
YOUR_FIELD: {
merge(existing = [], incoming: any) {
return { ...existing, ...incoming };
// this part of code is depends what you actually need to do, in my
case i had to save my incoming data as single object in cache
}
}
}
}
}
})
});
数据值与我们的架构不一致也有同样的问题。实体中的值类型缺少 id 值。 由不完整的数据迁移引起。
临时解决方案:
const typePolicies = {
PROBLEM_TYPE: {
keyFields: false as false,
},
PARENT_TYPE: {
fields: {
PROBLEM_FIELD: {
merge: true
}
}
}
}
这是 Thomas 提到的相同解决方案,但更短一些
const cache = new InMemoryCache({
typePolicies: {
Query: {
fields: {
YOUR_FIELD: {
// shorthand
merge: true,
},
},
},
},
});
这个和下面的一样
const cache = new InMemoryCache({
typePolicies: {
Query: {
fields: {
YOUR_FIELD: {
merge(existing, incoming, { mergeObjects }) {
return mergeObjects(existing, incoming);
},
},
},
},
},
});
其他答案仍然有效,但从 Apollo Client >= 3.3 开始,有一个 easier option 不需要指定特定字段或自定义合并函数。相反,您只需指定类型,它将合并该类型的所有字段:
const cache = new InMemoryCache({
typePolicies: {
YOUR_TYPE_NAME: {
merge: true,
}
}
});
根据您的示例查询,我猜 id
字段应该可用?尝试在查询中请求 ID,这应该可以更理想地解决问题。