Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cache.modify - Expose args passed to field modified fields #259

Open
jkdowdle opened this issue Aug 28, 2020 · 3 comments
Open

cache.modify - Expose args passed to field modified fields #259

jkdowdle opened this issue Aug 28, 2020 · 3 comments
Labels
📕 cache Feature requests related to the cache

Comments

@jkdowdle
Copy link

jkdowdle commented Aug 28, 2020

cache.modify - Expose args passed to field modified fields

What I am hoping to accomplish with this feature request may already exist in some form and maybe I am just misunderstanding how to do it or need to rely on a field merge policy or just the exposed storeFieldName

The problem I am hoping to solve is that when an entity within the cache is updated there could be any number, sometimes even double-digit queries that need to be updated on the client. Unfourtionatley in our apps uses case, even without considering extra round trips to the server, invalidating queries will not work because sometimes the data on the backend is not updated for 5 or more seconds. Eventual consistency issues.

With Apollo Client 3.0 we now have cache.modify which seems vastly simpler than the previous ways we've tried to use readQuery and writeQuery to update all the necessary queries.

However, I was a bit surprised when I noticed that I don't have access to the variables for a query field from within cache.modify except for in a serialized form.

const [addBook] = useMutation(
    gql`
      mutation AddBook {
        addNewBook {
          id
          name
          description
          likes
        }
      }
    `,
    {
      update(client, { data }) {
        const book = data.addNewBook;
        const newBookRef = client.writeFragment({
          data: book,
          fragment: gql`
            fragment NewBook on Book {
              id
              name
              description
            }
          `,
        });
        client.modify({
          fields: {
            books(existing, { args, storeFieldName, fieldName, }) {
              args // undefined
              fieldName // "books" 
              storeFieldName //  first query - "books:{"sort":"normal"}",  second query  -"books:{"sort":"reverse"}", 
              if (storeFieldName === 'books:{"sort":"reverse"}') {
                return [newBookRef, ...existing];
              }
              if (storeFieldName === 'books:{"sort":"normal"}') {
                return [...existing, newBookRef];
              }
            },
          },
        });
      },
    }
  );

This seems to work, but I was wondering if we could just expose could add an args property there that could be constructed by deserializing the variables used for storeFeildName, or maybe there is an existing cache utility that is exported to serialize an object into the storeFieldName? Just to make sure that we stay consistent with the cache.

Another thing that seems to work, if my modify field function returns nothing, it seems like it falls back to the merge function defined in the field's type policy.

client.modify({
  fields: {
     books(existing, { args, storeFieldName, fieldName }) {},
  },
});
cache: new InMemoryCache({
  typePolicies: {
    Book: {
      keyFields: ["id"],
      fields: {},
    },

    Query: {
      fields: {
        books: {
          keyArgs: ["sort"],
          merge(existing = [], incoming, { args }) {
            args // { sort: 'reverse' | 'normal' }
            if (args.sort === "reverse") {
              return [...incoming, ...existing];
            }
            if (args.sort === "normal") {
              return [...existing, ...incoming];
            }
          },
        },
...

Am I missing something? is there a better way to orchestrate some of these cache updates? Is there a reason that args or variables couldn't be included as part of the parameters for the cache.modify field updater like it is available in the merge/read type policies?

Anyway, really appreciate the work you all have done with maintaining and working on this library! I'm really excited about the version 3 release and hope to get through upgrading our current project to be using it in production soon!

@anark
Copy link

anark commented Sep 19, 2020

It would be great if the args were exposed. Currently you can parse the storedFieldName as follows
const args = JSON.parse(storeFieldName.replace(`${fieldName}:`, '')) but it would be much better if there was a supported way of doing this.

@anark
Copy link

anark commented Sep 19, 2020

Related to #238

@benjamn
Copy link
Member

benjamn commented Nov 11, 2020

Here's my current thinking about this idea: apollographql/apollo-client#7129

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
📕 cache Feature requests related to the cache
Projects
None yet
Development

No branches or pull requests

5 participants