Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Apollo: Refetch queries that have multiple variable permutations after mutation

Tags:

apollo

Let's say I have a table that lists a bunch of Posts using a query like:

const PostsQuery = gql`
  query posts($name: string) {
    posts {
      id
      name
      status
    }
  }
`;

const query = apolloClient.watchQuery({query: PostsQuery});
query.subscribe({
  next: (posts) => console.log(posts) // [ {name: "Post 1", id: '1', status: 'pending' }, { name: "Paul's Post", id: '2', status: 'pending'} ]
});

Then later my user comes along and enters a value in a search field and calls this code:

query.setVariables({name: 'Paul'})

It fetches the filtered posts and logs it out fine.

// [ { name: "Paul's Post", id: '2', status: 'pending'} ]

Now, in my table there is a button that changes the status of a post from 'Pending' to 'Active'. The user clicks that and it calls code like:

const PostsMutation = gql`
   mutation activatePost($id: ID!) {
     activatePost(id: $id) {
        ok
        object {
           id
           name
           status
        }
     }
   }
`;
apolloClient.mutate({mutation: PostsMutation});

All is well with the mutation, but now I want to refetch the table data so it has the latest, so I make a change:

apolloClient.mutate({
  mutation: PostsMutation,
  refetchQueries: [{query: PostsQuery, variables: {name: 'Paul'}]
});

Hurray, it works!

// [ { name: "Paul's Post", id: '2', status: 'active'} ]

But... now my user clears the search query, expecting the results to update.

query.setVariables({});

// [ {name: "Post 1", id: '1', status: 'pending' }, { name: "Paul's Post", id: '2', status: 'pending'} ]

Oh no! Because the data was not refetched in our mutation with our "original" variables (meaning none), we are getting stale data!

So how do you handle a situation where you have a mutation that may affect a query that could have many permutations of variables?

like image 510
Paul Avatar asked Apr 06 '26 19:04

Paul


1 Answers

I had a similar issue, I am using Apollo with Angular, so I am not sure if this method will work with React Client, but it should.

If you look closely at refetchQueries properties on the mutate method, you will see that the function can also return a string array of query names to refetch. By returning just the query name as a string, you do not need to worry about the variables. Be advised that this will refetch all the queries matching the name. So if you had a lot queries with different variables it could end up being a large request. But, in my case it is worth the trade off. If this is a problem, you could also get access to the queryManager through apolloClient.queryManager which you could use to do some more fine grained control of what to refetch. I didn't implement it, but it looked very possible. I found the solution below fits my needs fine.

In your code, what you need to do is:

apolloClient.mutate({
 mutation: PostsMutation,
 refetchQueries: (mutationResult) => ['PostQueries']
});

This will refetch any query with the name 'PostQueries'. Again, it is possible to only refetch a subset of them if you dig into the queryManager and do some filtering on the active watch queries. But, that is another exercise.

like image 189
Ray Suelzer Avatar answered Apr 08 '26 09:04

Ray Suelzer



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!