Use apollo-link to fetch a query upon any mutation

1k Views Asked by At

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!

1

There are 1 best solutions below

1
On

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)