阿波罗客户端缓存
Apollo Client cache
我刚开始在 React 应用程序上使用 apollo 客户端,但一直卡在缓存上。
我有一个包含产品列表的主页,我在其中查询以获取这些产品的 ID 和名称,还有一个产品页面,我在其中查询 ID、名称、描述和图像。
我希望如果用户首先访问主页,然后访问特定的产品页面,只查询该产品的描述和图像,并在加载过程中显示名称(因为我应该已经缓存了它) .
我遵循了 "Controlling the Store" 部分文档 (http://dev.apollodata.com/react/cache-updates.html),但仍然无法解决。
当我们转到产品页面时完成的查询仍然要求提供产品的 ID 和名称,但应该将它们缓存起来,因为我已经要求过它们。
我想我遗漏了什么,但我想不通。
这是一些代码:
// Create the apollo graphql client.
const apolloClient = new ApolloClient({
networkInterface: createNetworkInterface({
uri: `${process.env.GRAPHQL_ENDPOINT}`
}),
queryTransformer: addTypename,
dataIdFromObject: (result) => {
if (result.id && result.__typename) {
console.log(result.id, result.__typename); //can see this on console, seems okey
return result.__typename + result.id;
}
// Make sure to return null if this object doesn't have an ID
return null;
},
});
// home page query
// return an array of objects (Product)
export default graphql(gql`
query ProductsQuery {
products {
id, name
}
}
`)(Home);
//product page query
//return an object (Product)
export default graphql(gql`
query ProductQuery($productId: ID!) {
product(id: $productId) {
id, name, description, image
}
}
`,{
options: props => ({ variables: { productId: props.params.id } }),
props: ({ data: { loading, product } }) => ({
loading,
product,})
})(Product);
我的控制台输出:
你的问题的答案其实分为两部分:
客户端实际上无法确定这些查询解析为缓存中的同一个对象,因为它们具有不同的路径。一个以 products
开头,另一个以 product
开头。客户端解析器有一个 open PR,它可以让您提示客户端在缓存中的何处可以找到内容,即使您没有明确查询它们也是如此。我预计我们会在一两周内发布该功能。
即使使用客户端解析器,Apollo Client 也不会完全按照您上面描述的方式执行操作,因为 Apollo Client 从 0.5 版本开始不再执行查询差异。相反,现在所有查询都是完全静态的。这意味着即使您的查询部分在缓存中,完整的查询也会被发送到服务器。 blog post.
中列出了很多优点
通过在选项中设置 returnPartialData: true
,您仍然可以首先显示缓存中的部分。
这个问题很老了,但是,有一个解决方案可以使用 cacheRedirects
将查询映射到正确的位置
在我的项目中,我有一个 projects
查询和一个 project
查询。
我可以像下面这样制作 cacheRedirect
:
const client = new ApolloClient({
uri: "http://localhost:3000/graphql",
request: async (operation) => {
const token = await localStorage.getItem('authToken');
operation.setContext({
headers: {
authorization: token
}
});
},
cacheRedirects: {
Query: {
project: (_, { id }, { getCacheKey }) => getCacheKey({ id, __typename: 'Project' })
}
}
});
然后当我加载我的仪表板时,有 1 个查询得到 projects
。然后当导航到单个 project
时。没有发出网络请求,因为它正在从缓存中读取
我刚开始在 React 应用程序上使用 apollo 客户端,但一直卡在缓存上。 我有一个包含产品列表的主页,我在其中查询以获取这些产品的 ID 和名称,还有一个产品页面,我在其中查询 ID、名称、描述和图像。
我希望如果用户首先访问主页,然后访问特定的产品页面,只查询该产品的描述和图像,并在加载过程中显示名称(因为我应该已经缓存了它) . 我遵循了 "Controlling the Store" 部分文档 (http://dev.apollodata.com/react/cache-updates.html),但仍然无法解决。
当我们转到产品页面时完成的查询仍然要求提供产品的 ID 和名称,但应该将它们缓存起来,因为我已经要求过它们。
我想我遗漏了什么,但我想不通。 这是一些代码:
// Create the apollo graphql client.
const apolloClient = new ApolloClient({
networkInterface: createNetworkInterface({
uri: `${process.env.GRAPHQL_ENDPOINT}`
}),
queryTransformer: addTypename,
dataIdFromObject: (result) => {
if (result.id && result.__typename) {
console.log(result.id, result.__typename); //can see this on console, seems okey
return result.__typename + result.id;
}
// Make sure to return null if this object doesn't have an ID
return null;
},
});
// home page query
// return an array of objects (Product)
export default graphql(gql`
query ProductsQuery {
products {
id, name
}
}
`)(Home);
//product page query
//return an object (Product)
export default graphql(gql`
query ProductQuery($productId: ID!) {
product(id: $productId) {
id, name, description, image
}
}
`,{
options: props => ({ variables: { productId: props.params.id } }),
props: ({ data: { loading, product } }) => ({
loading,
product,})
})(Product);
我的控制台输出:
你的问题的答案其实分为两部分:
客户端实际上无法确定这些查询解析为缓存中的同一个对象,因为它们具有不同的路径。一个以
products
开头,另一个以product
开头。客户端解析器有一个 open PR,它可以让您提示客户端在缓存中的何处可以找到内容,即使您没有明确查询它们也是如此。我预计我们会在一两周内发布该功能。即使使用客户端解析器,Apollo Client 也不会完全按照您上面描述的方式执行操作,因为 Apollo Client 从 0.5 版本开始不再执行查询差异。相反,现在所有查询都是完全静态的。这意味着即使您的查询部分在缓存中,完整的查询也会被发送到服务器。 blog post.
中列出了很多优点
通过在选项中设置 returnPartialData: true
,您仍然可以首先显示缓存中的部分。
这个问题很老了,但是,有一个解决方案可以使用 cacheRedirects
在我的项目中,我有一个 projects
查询和一个 project
查询。
我可以像下面这样制作 cacheRedirect
:
const client = new ApolloClient({
uri: "http://localhost:3000/graphql",
request: async (operation) => {
const token = await localStorage.getItem('authToken');
operation.setContext({
headers: {
authorization: token
}
});
},
cacheRedirects: {
Query: {
project: (_, { id }, { getCacheKey }) => getCacheKey({ id, __typename: 'Project' })
}
}
});
然后当我加载我的仪表板时,有 1 个查询得到 projects
。然后当导航到单个 project
时。没有发出网络请求,因为它正在从缓存中读取