Apollo-client: mutation results are not updating cached objects in store

Created on 16 Jan 2017  路  11Comments  路  Source: apollographql/apollo-client

Apollo store seems to not update object with results coming from a mutation. Not sure if this is a bug, not implemented feature or misunderstanding of me?

The docs say for updateQueries:

UI should just update automatically based on the result of a mutation as long as modified fields of objects and the object identifiers of modified objects are returned with the mutation (see the dataIdFromObject documentation above for more information).

I'm running a mutation against the server and return the updated object. My expected behavior of apollo-client store is that the returned object should updated the internal store and propagate changes reactively without having to write updateQueries statements if the dataIdFromObject is set. In this case the ui is updated lazy and not optimistic.

apollo-client cache updates are set up as in the docs.

const client = new ApolloClient({
  dataIdFromObject: (o) => {
    console.log("dataIdFromObject",o);
    return`${o.__typename}-${o.id},`;
  }
});

I have a split application view, left a list view and right a detail editor

ngInit() {
  this.apollo.watchQuery({
       query: gqlQueryMyPosts
  }).subscribe(
      (d) => {
         console.log("query", d);
         this.posts = d.data;
      } 
  );
}
function onSave() {

this.apollo.mutate({
        mutation: gqlSavePost,
        variables: {
            id: post.id,
            title: post.title
        }
    }).subscribe(
        (d) => console.log("mutation", d);
    );
}
````

this results in the following console.log:

dataIdFromObject Object
dataIdFromObject Object
...
query [Object, {id:2, title:"old", ...}...]

editing post pressing post save button triggering onSave()
query [Object, {id:2, title:"old", ...}...] << reactively fired update with the changed object not being updated, thats ok. response ist not yet here
mutation {id:2, title:"new", ...} << this is updated object from server with changed Object
query [Object, {id:2, title:"old", ...} ...] << reactively fired update, but still returning old data from the first query

I would have expected that with the mutation the dataIdFromObject would fire to identify the returned object. But this is not happening either.

I'm not sure if this is related bug discussed in issue #1123 

using:

"apollo-client": "^0.7.0",
"angular2-apollo": "^0.9.0-rc.5",
```

Most helpful comment

Not sure if this is relevant, but I have the store objects updating fine when they have a standard id like __typename:id but not when they are singular "$ROOT_QUERY.typename", probably right?

All 11 comments

Can you add the query and mutation strings to your report?

I'm seeing this same issue (with react-apollo). I've even tried manually setting updateQueries with no luck. If it helps, here is my query and mutation string:

const updateMutation = gql`
  mutation UpdateCampaignInfo($id: String!, $name: String, $deployedAt: String,
    $publishBefore: String) {
      updateBasicInfo(id: $id, name: $name, deployedAt: $deployedAt, publishBefore: $publishBefore) {
        id
        state
        name
        deployedAt
        publishBefore
      }
  }
`;

const getQuery = gql`
  query GetCampaignBasicInfo($id: String!) {
    campaign(id: $id) {
      id
      state
      name
      deployedAt
      publishBefore
    }
  }
`;

As an update, mine was due to #1123. I wasn't passing in optional variables which was causing bugs in the mutation, which has been addressed in master for the next release.

My mutation is working, even though not passing all optional parameters.

I'm passing all variable written in the query however not passing all optional parameters, which the server can accept. e.g:

in the query (angular 2 client)

mutation postSave(
  $id: Int!,
  $title: String,
) {
  postSave(
    id: $id,
    title: $title,
  ) {
    ...PostDataFragement
  }
}

with

variables = {
  id: 123
  title: "some sample"
}

the server would also accept more optional parameters

type RootMutation {
  postSave(
    id: Int!,
    authorId: Int,
    title: String,
    content: String,
  ): Post
}`;

I had the same issue... my mutation was working but the cache wasn't updating. I fixed it by passing in null (or some default value) for the optional parameters even if I wasn't using them. not sure if that will help you or not.

@manuelfink could you try with 0.8.0? If it still does not work can we see the results from the query and mutation? Is the __typename the same for the object you are creating and the one you want to update?

@calebmer not tested in detail yet, but it seems to work with 0.8.0 and latest angular-apollo version.

Not sure if this is relevant, but I have the store objects updating fine when they have a standard id like __typename:id but not when they are singular "$ROOT_QUERY.typename", probably right?

I had this same issue, but discovered that if your mutation (or whatever interaction is triggering the cache update) doesn't return fields that are designated nonnull in your schema, the cache will not update.

I'm having the same exact issue with multiple mutations. One for example...

type ItemProperty {
    id: Int!
    item: Item
    notes: String
    type: Int!
    value: String!
}

fragment ItemPropertyAllFields on ItemProperty {
        id
        type
        value
        notes
}

input UpdateItemPropertyInput {
    itemId: Int
    notes: String
    type: Int
    value: String
}

mutation UpdateItemProperty($id: Int, $input: UpdateItemPropertyInput) {
    updateItemProperty(id: $id, input: $input){
        ...ItemPropertyAllFields
    }
}

query ItemPropertiesByItemId($itemId: Int) {
        itemProperties(where: { AND: [{ itemId: { is: $itemId } }] }) {
            id
            type
            value
            notes
        }
    }

After I run the UpdateItemProperty mutation, I also need to refetch ItemPropertiesByItemId, otherwise nothing in the UI will update. I've tried manually updating the cache as well but my attempts of that have since failed.

"apollo-boost": "0.4.4",
"apollo-client": "2.6.4",
"apollo-link": "1.2.12",
"apollo-cache": "1.3.2",
"apollo-utilities": "1.3.2",
"apollo-cache-inmemory": "1.6.3",

I'm having the same exact issue with multiple mutations. One for example...

type ItemProperty {
    id: Int!
    item: Item
    notes: String
    type: Int!
    value: String!
}

fragment ItemPropertyAllFields on ItemProperty {
        id
        type
        value
        notes
}

input UpdateItemPropertyInput {
    itemId: Int
    notes: String
    type: Int
    value: String
}

mutation UpdateItemProperty($id: Int, $input: UpdateItemPropertyInput) {
    updateItemProperty(id: $id, input: $input){
        ...ItemPropertyAllFields
    }
}

query ItemPropertiesByItemId($itemId: Int) {
        itemProperties(where: { AND: [{ itemId: { is: $itemId } }] }) {
            id
            type
            value
            notes
        }
    }

After I run the UpdateItemProperty mutation, I also need to refetch ItemPropertiesByItemId, otherwise nothing in the UI will update. I've tried manually updating the cache as well but my attempts of that have since failed.

"apollo-boost": "0.4.4",
"apollo-client": "2.6.4",
"apollo-link": "1.2.12",
"apollo-cache": "1.3.2",
"apollo-utilities": "1.3.2",
"apollo-cache-inmemory": "1.6.3",

I'm pretty sure it has to do with the variables being optional or different. It is also a problem on nested arguments. You might be able to use to @connection directive to make a more stable store key...

Was this page helpful?
0 / 5 - 0 ratings