DEV Community

Apollo state management in Vue application

Natalia Tepluhina on May 01, 2019

This article assumes you already know what GraphQL and Apollo client are and you're able to build Vue applications with Vue CLI 🤔 Why d...
Collapse
 
stfnwp profile image
Stefan Prosiegel

Definitely a useful post for devs wanting to give this kind of local state management a try!
But I still don't get the point of using GraphQL for local state management.
If your app doesn't neccessarily need caching you could still rely on low-level graphql fetching using apollo-link-http and wire it up with a traditional vuex store.
Then you have a lightweight setup and the vuex advantages (like time travelling) and no need to utilize functions with weird/unused arguments (like "_") and you don't have any doubled code because you store the response data inside your store.
Anyway a great to follow and really detailed article... But yet I wish those contemporary tech articles would have a more "debated view" ;-)

Collapse
 
dima04869562 profile image
Dima

Hi Natalia!
Great article! Thanks!

But what about large applications where Vuex is unobtainable?
How to build a structure there?
If we get data (graphql) and work with them in the application?

Use graphql + Vuex only?

Or is it more optimal Apollo-Vue + Vuex?

Collapse
 
n_tepluhina profile image
Natalia Tepluhina

Thank you! Right now I would go with Apollo Client (cache disabled)+ Vuex without vue-apollo. If you wonder, how to make it all work together, I've created a small proof of concept when researching Vuex -> Apollo migration for GitLab: gitlab.com/ntepluhina/vuex-to-apollo

The repo has a detailed descriptive readme and one of the branches addresses this approach :)

Please let me know if you have any questions

Collapse
 
smolinari profile image
Scott Molinari

Hi,

Can you please elaborate on the reasoning for this and not using Apollo's client state? Wouldn't it just be a question of modularizing local state queries and mutations, similar to what would be necessary with Vuex too?

Scott

Collapse
 
stefanflaschko profile image
StefanFlaschko

Unfortunately this gitlab repro is also out of date. When trying to install it with npm install, there are several errors comming up because of not existing and no longer maintained packages.

Collapse
 
dima04869562 profile image
Dima

Natalya, thanks!
This is probably the best practice ffor this moment.

Collapse
 
tarabass profile image
Peter Rietveld

Hello Natalia, I followed your tut to get familiar with Apollo cache. Thx for that!

Maybe I missed it, but you are never adding the exported resolver to the options object when instantiating the ApolloClient object. So my resolver didn't work. After some debugging and research I found that resolvers: {} was still there and had to replaced with the resolvers we made further on.

For others:

In main.js

change

import { typeDefs } from './resolvers'

to

import { typeDefs, resolvers } from './resolvers'

and

const apolloClient = new ApolloClient({
  cache,
  typeDefs,
  resolvers: {},
})

to

const apolloClient = new ApolloClient({
  cache,
  typeDefs,
  resolvers,
})
Collapse
 
n_tepluhina profile image
Natalia Tepluhina

Hi Peter! I do this in Creating a local schema part. There is a note there:

Please note the empty resolvers object here: if we don't assign it to the Apollo client options, it won't recognize the queries to local state and will try to send a request to remote URL instead

Collapse
 
tarabass profile image
Peter Rietveld

I was reading that as for now we assign an empty object, else we get in trouble :P

Collapse
 
renestalder profile image
René Stalder

Is it correct to use cache.writeQuery and cache.readQuery? I found that this currently doesn't work for me (state doesn't get updated) and the documentation of Apollo notes:

The cache you created with new InMemoryCache(...) class is not meant to be used directly, but passed to the ApolloClient constructor. The client then accesses the cache using methods like readQuery and writeQuery. The difference between cache.writeQuery and client.writeQuery is that the client version also performs a broadcast after writing to the cache. This broadcast ensures your data is refreshed in the view layer after the client.writeQuery operation. If you only use cache.writeQuery, the changes may not be immediately reflected in the view layer. This behavior is sometimes useful in scenarios where you want to perform multiple cache writes without immediately updating the view layer.

apollographql.com/docs/react/advan...

Collapse
 
n_tepluhina profile image
Natalia Tepluhina

I fixed it in the article: we use writeData, not writeQuery ;)

Collapse
 
renestalder profile image
René Stalder

I rather meant in the mutations inside the resolver. With client.writeQuery you can make sure, the data reactivity is triggered for sure while cache.writeQuery will possible not fire a data refresh in your UI if you change nested items. At least that's what I currently can reproduce.

Thread Thread
 
n_tepluhina profile image
Natalia Tepluhina

I cannot reproduce this behavior and very own Apollo tutorials are also relying on cache.writeData and cache.writeQuery
apollographql.com/docs/react/essen...

Collapse
 
austinbv profile image
Austin Vance

I love this post! one thing I would love to do is abstract away the fact that we have a Apollo Mutation from the components.

I'm not sure if it's realistic but I was thinking of the situation where you have a snackbar or toasts. You could have local state with Vue-Apollo but I want to create an interface to my AlertService that doesn't expose VueApollo.

I feel like I am rambling like a madman, but, have you ever tried to hideaway any of your Apollo logic?

Collapse
 
n_tepluhina profile image
Natalia Tepluhina

You can do it outside of the components and without VueApollo :) In fact, VueApollo works as a Vue wrapper for Apollo Client, but it doesn't mean you can't use the client directly:

First, you will need to export your client when creating it:

export const apolloClient = new ApolloClient({...});

Then, you can import it anywhere in the service/util/helper and use it:

import { apolloClient } from './index';

apolloClient.mutate({
  variables: { text: "hello" },
  mutation: myMutation,
})
.then(result => { console.log(result) })
.catch(error => { console.log(error) });
Collapse
 
austinbv profile image
Austin Vance

Such an awesome response - I just did something similar but I needed to be able to mock in test so I have a service that looks like this

export default class AlertService {
  constructor(private client: ApolloClient<InMemoryCache>) {
    this.client = client;
  }
  // ...
}

Then I inject the real client on Vue.js startup

  Vue.prototype.$alertService = new AlertService(apolloProvider.defaultClient);

Then in a test I can inject a mock.

Thread Thread
 
n_tepluhina profile image
Natalia Tepluhina

Awesome mock! I'm happy the reply was useful :)

Collapse
 
jojko profile image
Jacob Janisz

How does it work with reactivity? Is the data still reactive if I use it with legacy ApolloClient e.x. for updating local state?

Collapse
 
renestalder profile image
René Stalder

You hit the nail on it's head: If one is gonna create an app or website coupled to GraphQL, this question will ultimately come up as soon as the discovery of Apollo Local State happens. And there is not much about best practices of integrating Apollo Local State into web apps other than the rather difficult to understand documentation. So your post is quite important. Thank you for that.

Collapse
 
n_tepluhina profile image
Natalia Tepluhina

Thank you so much! I am really thrilled this post is useful 🤗

Collapse
 
stefanflaschko profile image
StefanFlaschko

The GitHub Rep is not working anymore. When running npm install there are several errors comming up because of outdated packages. Would be really nice to have an up to date version of this little project with Vue3 and the composition API. Or Maybe someone can point me to another example project. So far I could not find anything useful.

Collapse
 
maazdev profile image
MaazDev

Thanks , but i still don't understand how to also update my remote graphql server x) i need to sent two queries ?

Collapse
 
toha28810336 profile image
toha

Thanks, lovely article. Vuex has perfect devtools. Vuex has getters. Vue Apollo sounds like twice less code and less memory usage.

Collapse
 
dimer22zhc profile image
Dimer

What about Laravel - vuex - vue-apollo #vuex #laravel #vue-apollo

Collapse
 
fregadetto profile image
Fredrik Ottedag

Good post. Thanks.