简体   繁体   中英

GraphQL/Apollo Client: get data from cache if a query is a subset of a previous query

I'm new to GraphQL and I thought it would do this automatically.

Eg if I fetch a list of posts, then open an individual post, the data for that post is already in memory. I expected GraphQL to be able to re-use the data from cache, but it makes another network request.

The schema is something like:

  type Query {
    posts: [Post]
    post(id: ID): Post
  }

I'm using React. In PostsRoute , I have:

  useQuery(gql`
    query {
      posts {
        id
        title
      }
    }
  `);

In PostRoute , I have:

  useQuery(gql`
    query {
      post(id: ${postId}) {
        id
        title
      }
    }
  `);

Is there something I need to configure for Apollo to use the cached data automatically? Or is this something that Apollo doesn't support by default?

Apollo 2

If you are using Apollo 2, what you're looking for is probably cacheRedirects . It is used to intercept a query and resolve it using the cache. The linked document actually explains exactly your use-case so I recommend you look at it, but for posterity, here's how I do it personally (adapted to your situation).

In your InMemoryCache options when you instantiate it, add a cacheRedirects field and specify a custom resolver for your post query, like so:

const cache = new InMemoryCache({
  cacheRedirects: {
    Query: {
      post: (_, {id}, {getCacheKey}) => getCacheKey({__typename: "Post", id}),
    },
  },
});

This assumes that the __typename of your post is Post . First argument of the custom resolver is the result of the ROOT_QUERY , which we don't use here. Second argument is the arguments that are passed to the query ( {id: "some_id"} here) and the third one is the context, containing client , cache and getCacheKey . Only getCacheKey is useful to us here. That method take a __typename and an id , and returns its key in the cache.

This completes the custom resolver. Now when you query post(id: some_id) it will look at the custom resolver, receive the cache key and return the result from the cache matching that key.

Apollo 3

cacheRedirects has been removed in Apollo 3, but the same functionality can be achieved with field policies . You still need to set it up when instantiating InMemoryCache , but it's slightly different:

const cache = new InMemoryCache({
  typePolicies: {
    Query: {
      fields: {
        post: (_, {args, toReference}) => toReference({__typename: "Post", id: args.id}),
      },
    },
  },
});

We define a field policy read on the field post on type Query . Note that the second argument now includes both args and the helper utilities. This includes toReference , that's basically the new getCacheKey .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM