Apollo-client: updateQueries will only update cache if keys in mutation variables exactly match mutation signature

Created on 5 Jan 2017  路  14Comments  路  Source: apollographql/apollo-client

Hi there!
I am new to graphql and apollo and building a small issue tracker to try them out.
I have come across this problem while trying to use updateQueries, to update a list after a mutation and I am not sure if this is intended behaviour or a bug:
if the payload of the mutation does not contain exactly the same keys as the parameters in the mutation signature, the return value of updateQueries will be ignored.

I have created a simple representation of the problem as follows:

query

const query = gql`
    query issues{
        issues {
            id
            title
            description
            project{
                id
                title
            }
        }
    }
`;

mutation

const mutation = gql`
    mutation createIssue($title: String!, $project: String!, $description: String){
        createIssue(title: $title, project: $project, description: $description){
            id
            title
            description
            project{
                id
                title
            }
        }
    }
`;

mutation HOC

const withMutation = graphql(mutation, {
    props: ({ownProps, mutate}) => {
        return {
            createIssue: data => mutate({
                variables: data,
                updateQueries: {
                    issues: (prev, action) => {
                        console.log(action);
                        const {mutationResult} = action;
                        const newIssue = mutationResult.data.createIssue;
                        return {
                            issues: [newIssue, ...prev.issues]
                        }
                    }
                }
            })
        }
    }
});

code calling mutation

const issue = {
    title: faker.hacker.phrase(),
    project: projectsIds[Math.floor(Math.random()*projectsIds.length)],
    description: 'test',
};

this.props.createIssue(issue).then(() => {
    console.log('created issue');
});

If I leave out the optional description key from the issue object, updateQueries will still run, but its return value will not be used to update the cache.

Is this intended behaviour, and if so, what is the reason it should work this way?

Thank you.

Most helpful comment

@mkozhukharenko I'm having the same exact issue. After a lot of digging and trying, I found out that the query mutation fields need to match the query that you want to update via updateQueries, or else something weird happens and the value will be undefined.

The linked issue seems to go into more detail.

All 14 comments

I think that's not intended behavior - it seems like what might be happening is that Apollo is internally expecting the shape of the new data to match the query and then failing silently for some reason when it does not. So there are two issues:

  1. It should throw or print an error if it is failing, and
  2. It shouldn't fail in the first place

Do you mind sending a PR with a test for this? It should go next to the other tests for updateQueries.

I must say I am not closely familiar with the internals of Apollo Client and I don't have a ton of experience with writing tests in general, but I can look into this during the weekend.
Is this the right file to work with?

@krksgbr I think you should see the same behavior when you just update a single query, so you can write the test in this file similar to the one that has "triggers new result from updateQuery" in the title, but instead do what you do in your case to make it fail. Thanks in advance for your efforts! 馃檪

I'm seeing something very similar over here where the update is just silently ignored. Would it be possible to warn users about rejected updates, rather than silently ignoring them?

@krksgbr thanks so much for your tests! I merged them into my current open PR trying to fix this (https://github.com/apollostack/apollo-client/pull/1174) and it looks like one of your two tests is fixed. I鈥檓 pretty sure that I know what needs to be done to fix the other one. Hopefully we can get a fix for this soon :+1:

@calebmer
Great! So can I close my own PR then?

I think the issue I'm having is related to this. I have a CurrentUser query that the server returns an error for when there is no logged in user. When a user logs in I want to update the CurrentUser query with what's returned from the mutation.

With updateQueries the previous result is a blank object (because the server returned an error because no current user exists), and the query doesn't get updated with the mutation result. This could be because the object shapes don't match (i.e. this issue), or possibly because the previous result had data.error.graphQLErrors....

I also tried implementing this with a reducer in the CurrentUser query instead, but the same problem occurred even though the correct data is available in action.result.data....

updateQueries: {
  CurrentUser: (prev, { mutationResult }) => {
    // prev is a blank object when the server returns an error for the previous result
    console.log(prev);
    return {
      viewer: {
        user: mutationResult.data.loginUser.user,
      },
    };
  },
},

Using: apollo-client 0.7.3, and react-apollo 0.8.1

@rafrex I don鈥檛 actually think this is the same issue. If it is you should be at least partially fixed by https://github.com/apollostack/apollo-client/pull/1174. Could you open a new issue so we can try to better understand your problem there?

@calebmer I opened a new issue #1201

I believe this is the right issue:
I'm also unable to add an item to a collection using updateQueries, if that collection is empty to begin with.

@CodogoFreddie do you have a small example / minimal reproduction? I'm guessing this isn't the same issue, but without a reproduction or failing test case it's pretty hard to tell.

I has the next issue and I think that it's the same that is discussing here:

docs says:

If you pass a query into your graphql() function then your component will fetch that query and reactively listen to updates for the query in the store.

When I鈥檓 updating store using updateQueries or update with proxy - the Store is updated, actually, and the my component is being rerendered. But no values comes into it (undefined).

I'll try to provide an example. It seems that the problem is in the query/mutation shape - but Apollo fails silently.

@mkozhukharenko I'm having the same exact issue. After a lot of digging and trying, I found out that the query mutation fields need to match the query that you want to update via updateQueries, or else something weird happens and the value will be undefined.

The linked issue seems to go into more detail.

This will become much easier to debug with #1638 which we'll merge and release today or tomorrow (just working on adding more tests now)!

Was this page helpful?
0 / 5 - 0 ratings