5

我刚开始在 React 应用程序上使用 apollo 客户端,但我被困在缓存上。我有一个包含产品列表的主页,我在其中进行查询以获取这些产品的 ID 和名称,以及一个产品页面,我在其中查询 ID、名称、描述和图像。

我希望如果用户访问主页,然后访问特定的产品页面,只查询该产品的描述和图像,在加载过程中也显示名称(因为我应该已经缓存了它)。我遵循了文档中的“控制商店”部分(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);

我的控制台输出:

控制台输出

4

2 回答 2

4

你的问题的答案实际上有两个部分:

  1. 客户端实际上无法确定这些查询解析到缓存中的相同对象,因为它们具有不同的路径。一个以 开头products,另一个以开头product。客户端解析器有一个开放的 PR,它可以让您向客户端提示在缓存中的何处查找内容,即使您没有明确查询它们。我希望我们将在一两周内发布该功能。

  2. 即使使用客户端解析器,Apollo Client 也不会完全按照您上面描述的那样做,因为 Apollo Client 自 0.5 版以来不再进行查询差异。相反,所有查询现在都是完全静态的。这意味着即使您的查询部分在缓存中,完整的查询也会被发送到服务器。这有许多优点,本博客文章中列出了这些优点。

returnPartialData: true通过设置选项,您仍然可以首先显示缓存中的部分。

于 2016-11-04T18:52:57.367 回答
1

这个问题已经很老了,但是,有一个解决方案可以将查询映射到正确的位置,使用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. 没有发出网络请求,因为它正在从缓存中读取

阅读有关缓存重定向的完整文档

于 2020-01-29T13:41:35.810 回答