When to use Apollo's cacheRedirects?

倾然丶 夕夏残阳落幕 提交于 2021-01-27 05:40:49

问题


The Apollo documentation discusses the use of cacheRedirects to tell Apollo how to access data that's already in the cache from other query.

It gives an example of this:

In some cases, a query requests data that already exists in the client store under a different key. A very common example of this is when your UI has a list view and a detail view that both use the same data. The list view might run the following query:

query ListView { books { id title abstract } }

When a specific book is selected, the detail view displays an individual item using this query:

query DetailView { book(id: $id) { id title abstract } }

We know that the data is most likely already in the client cache, but because it’s requested with a different query, Apollo Client doesn’t know that. In order to tell Apollo Client where to look for the data, we can define custom resolvers

I'm trying to understand why this is necessary for this example. If the books query returns an array of type Book, and the book request returns a single object of type Book, then surely the normalised cache will already have data for each of the books (from the ListView query) based on the typename and id, and the DetailView query can use that information directly without any further intervention. Instead, we're told for write some code to help it:

const cache = new InMemoryCache({
  cacheRedirects: {
    Query: {
      book: (_, args, { getCacheKey }) =>
        getCacheKey({ __typename: 'Book', id: args.id })
    },
  },
});

Underwhat exactly which circumstance is the ApolloClient not able to figure this out for itself, and why?


回答1:


It seems obvious and intuitive that given a query like the one below that we're fetching a single Book object by it's id property.

query DetailView($id: ID) {
  book(id: $id) {
    id
    title
    abstract
  }
}

However, in this example the name of the argument here (id) just happens to match the name of the property used by the cache (id). Outside convention, there's nothing that says the argument itself couldn't be called bookId, bookID or supercalifragilisticexpialidocious. Even if a query returns a Book type and takes one or more arguments, Apollo has no way to infer which argument is in fact the id that was used in cache normalization. Similarly, if other arguments exist, they may or may not matter in respect to whether what's currently cached can be used or not -- further logic is needed to determine that.

The other consideration here is that outside of optionally passing in an instance of IntrospectionFragmentMatcher to your InMemoryCache, Apollo is not actually aware of what the schema is of the endpoint it queries. The types used by the cache in normalization are determined after a query is fetched using the __typename property. The whole point of cacheRedirects is to prevent a query from being fired if the item or items are already in the cache. However, given a particular query, Apollo has no way to know that it will return a particular type until after that query returns. cacheRedirects provides a way to say "this query will return this particular type" without ever having fired the query in the first place.




回答2:


Just an afterthought: this is inherently due to the GraphQL design. In GraphQL, book(id) its resolver is free to interpret id any way they like. It is simply a function call with a single parameter, which happens to return an instance of type Book.

GraphQL actually says nothing about IDs whatsoever. It only recognizes __typename as special.

Only Relay, and to some extent Apollo, add a notion of object IDs later. They take a bit different approach though, with Relay mandating your GraphQL schema into a more rigid, formal structure.

There is even additional complication (mentioned by the other answer too) about schema not being available to the client (so the client does not even know book will return Book without making the query). This again follows from GraphQL spec.



来源:https://stackoverflow.com/questions/52927310/when-to-use-apollos-cacheredirects

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!