3

I am working on an application where there are projects with a nested tree of assets. In the backend, the changed-date of the project is updated when one of the children of grandchildren (or grand-grand-children) is updated.

In react-apollo, I have set-up all queries such that the updated object is returned and the cache of apollo is updated with the updated data. But I would also like to update the changed-date of the project (which may be a parent, grandparent, etc).

One solution is to use the refetchQueries option. However, that would mean I need to implement this refetchQueries option in all pieces where the useMutation hook is used, which causes a lot of code duplication plus the risk that it may be forgotten by other developers (team of 4). A better option is to create a custom hook that wraps the useMutation hook, but devs still need to use it.

So I am now looking at using apollo-link for this, which will affect all mutations performed. However, I can't figure out if it is possible to add a query to the operation, or to queue a query, and if possible - how to do it?

Thanks for your help!

ErikRtvl
  • 326
  • 1
  • 7

1 Answers1

0

Using ApolloLink you could generate linked afterware to parse returned responses, and conditionally update the cache in appropriate cases.

    import { ApolloLink } from "apollo-link";
    import { createHttpLink } from "apollo-link-http";
 
    const httpLink = createHttpLink({ uri: "/graphql" });
    const updateDateCacheLink = new ApolloLink((operation, forward) => {
       return forward(operation).map(response => {
           const context = operation.getContext();
           const { response: { headers } } = context;
    
           /* conditionally update cache */     

         return response;
     });
   });
 
    // use with apollo-client
    const link = updateDateCacheLink.concat(httpLink);


Alternatively, you might consider using a HOC returning a component that implements the update callback of useMutation, which receives the update payload. This would avoid duplication and encapsulate the common caching logic consistent with your request. And as you noted a custom hook could wrap and be used in place of useMutation (not shown below).

const withMutationCacheUpdate = args => Wrapped => {
  return function(props) {
    const [updateData] = useMutation(UPDATE_DATA, {
      update(cache, { data: { newData } }) {
        // Read relevant data from cache with cache.readQuery,
        // then update using cache.writeQuery, cache.writeFragment 
       // or cache.modify as appropriate with returned payload and possibly args
      },
    })
    return <Wrapped {...props} updateData={updateData} />
  }
}

const config = {...}
const YourComponent = props => { ... }
const YourWrappedComponent = withMutationCacheUpdate(config)(YourComponent)
Greg Brodzik
  • 1,765
  • 7
  • 9
  • 1
    Thanks for your reply! However, my hope was that it would be possible to actually add another query (i.e. "query { projects { changed } }") whenever an mutation is made. So that the returned response is actually more than specified in the mutation-query. But I believe this is not possible, after many searches on the internet. So I have now provided a new custom hook that always performs an additional quer using the "refetchQueries" option. We will use this custom hook as a drop-in replacement of "useMutation" – ErikRtvl Oct 22 '20 at 15:49