apollo-link-state icon indicating copy to clipboard operation
apollo-link-state copied to clipboard

Equivalent to `replaceReducer`?

Open eric-burel opened this issue 5 years ago • 3 comments

Hi, I am currently trying to replace the use of redux in the Vulcan.js framework (built on top of Meteor) with apollo-link-state. Meteor being package based, we used to allow people to register additional reducers to the centralized redux store. Internally, this feature relied on the Redux store replaceReducer. I am looking for an equivalent pattern with apollo-link-state. It means being able to add Mutation after the link is created. Let's call this function addMutation for example.

My first naive idea is to create a new link when the user call addMutation, and then instantiate a new client with this new link, but with keeping the old cache. However, it feels not very clean. In Redux, this would be equivalent to getting the current store state, creating a new store with up-to-date reducers, and rehydrating it with the previous state, instead of using replaceReducer. Edit: another solution is to defer the apollo client until all packages have registered their mutation in a central object. But still, a function like replaceLinks or replaceStateLinkResolvers in the client could be interesting for some advanced use cases.

My question is: did I miss some helper I could use, and do you have a better pattern that would be equivalent to Redux store replaceReducer?

Let me know if I should post this on StackOverflow instead, however since apollo-link-state seeks to be a replacement for Redux I thought my question belonged more here since replacing reducers is normal pattern in Redux.

eric-burel avatar Sep 26 '18 13:09 eric-burel

@eric-burel We're working on a new version of apollo-link-state that should accommodate this. The new approach is no longer Apollo Link based, and is instead wired directly into Apollo Client. The new API supports adding resolvers at any point, by calling:

...
client.addResolvers({
  Mutation: {
    someNewMutation(_, args, context) {
      ... resolver stuff
    },
  },
});
...

Will this work for you?

hwillson avatar Oct 13 '18 17:10 hwillson

That sounds excellent, thanks! Note that I'd also expect this function to be able to replace an existing resolver if the name is the same. This would allow to wrap an existing resolver for example. I am not sure about the use cases yet, Apollo is still new to me, but I'm thinking about dev tools, logging, enhancing context, advanced features provided by plugins that enhances the resolvers etc. For example I imagine an usage like this:

const unwrappedMutation = client.resolvers.Mutation.myExistingMutation
client.addResolvers({
  Mutation: {
    myExistingMutation(doc, args, context) {
     // add some feature to the mutation, eg enhancing context with current userId
      const newContext = {...context, userId: context.userId || localStorage.userId }
      // call existing mutation
      unwrappedMutation(doc, args, newContext)
    }
  }
})

eric-burel avatar Oct 14 '18 13:10 eric-burel

Great, thanks for the feedback @eric-burel! Re: replacing a resolver with the same name; yes, that's doable with the new API. More details soon - thanks!

hwillson avatar Oct 14 '18 13:10 hwillson