1

I have a working mutation call in my Angular application for mutating some fields for an object with Apollo GraphQL. Part of the mutation call includes some return data that Apollo will associate with some object already in its cache and update it with the new value returned.

I would like to only return fields that are actually being mutated to avoid big packets being sent across the network.

I've managed to dynamically generate a mutation document that only includes fields being mutated and I'm passing that into apollo.mutate({mutation: newMutation, ...}) which returns an observable. The mutation only fires once that observable is subscribed to. I've verified that the component using that subscription is unsubscribing and being destroyed before the new mutation is called.

The problem is that Apollo is caching the mutation document and sending out the first mutation (with only fields mutated the first time) for all calls. I've verified this by checking my web browser's Network tab.

I've tried getting Apollo to stop caching it by using unique mutation names by appending datetime. I've checked that variables to the mutation are unique. I've tried using fragments, yet the fragments would also need to be dynamically generated and it's the same issue.

Anyone know what I'm doing wrong?

2
  • prepare minimal reproducible example - send/receive an array of key/val (write cache)? Commented Apr 3, 2020 at 20:07
  • Apollo Client by itself would not do this. The only caching Apollo does is of query results -- it does not cache the DocumentNodes passed to it. There is most likely something else in your code that's causing this behavior -- maybe a Link if you use something other than HttpLink or some custom wrapper you've written over Apollo's API? Commented Apr 3, 2020 at 22:38

2 Answers 2

2

Okay, I figured it out. Apollo Client is adding mutation documents to its ROOT_MUTATION. I've found that using Apollo Client's writeData/writeQuery functions only let you add/modify the ROOT_QUERY.

Originally I was trying to dynamically add fields to my GraphQL AST. The code looked something like this:

import gql from 'graphql-tag';
...
const myMutation = gql`
  mutation myMutation($id: ID!, ...) {
    mutateFields(id: $id, ...) {
      id  # You need to return at least one field or it will complain
      # Add mutated fields to return here
    }
  }
`;

# dynamically call the following lines based on fields to be added
myMutation.definitions[0].selectionSet.selections[0].selectionSet.selections = [
  {...}  # Added my own fields and their subfields here
];

The problem was that it worked the first time, so I knew I was correctly modifying the GraphQL AST, yet subsequent calls (with new fields to return) were correctly created but Apollo was sending out the first mutation of the same name (I checked my Browser's Network tab to verify).

THE SOLUTION:

Don't modify the GraphQL AST, instead modify it as a string literal similar to the comment by Alireza Hariri on this post: GraphQL dynamic query building.

Sample code:

const mainMutation = `
   mutation myMutation($id: ID!, ...) {
    mutateFields(id: $id, ...) {
      id  # You need to return at least one field or it will complain
      # REPLACE_THIS_WITH_FIELDS
    }
  }
`;

const mutationWithFields = mainMutation.replace(
  `# REPLACE_THIS_WITH_FIELDS`,
  "myField { mySubfield1 mySubfield2 }"
);

const finalMutation = gql`${mutationWithFields}`;
this.apollo.mutate({
  mutation: finalMutation,
  variables: {
    id: myId,
    ...
  }
});
Sign up to request clarification or add additional context in comments.

Comments

0

I know this is old, but i make a package to allow build dynamic selection sets based on entities interfaces decorators. Check my packages:

This one for base feature with apollo-client: https://www.npmjs.com/package/apollo-dynamic And this one for use with apollo-angular: https://www.npmjs.com/package/apollo-dynamic-angular

I use it in my projects and works pretty fine. Here's the app template im making now that use this library and other ones: https://github.com/giuliano-marinelli/app-client . I invite you to check it too (it's not finished yet)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.