-
-
Notifications
You must be signed in to change notification settings - Fork 522
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
vue-apollo and vuex interaction best practices #140
Comments
@alidcastano I'll tell you from my experience (I'm building a chat application, something like Slack)... I was also a big fan for Vuex when using REST. But after using Apollo client, I no longer needs Vuex. Vuex is some sort of Flux/Redux implementation. It's already built in Apollo client. All data I need is inside the Apollo cache, and I access it directly. You have full access to that cache so that you can insert, update and do everything with it. So after playing with Apollo client cache I really think there is no need for Vuex (in my case). But in some cases, I still need a simple centralized store to save some information like Again, it's from my experience. Maybe it doesn't fit for you. What are you building? Waiting for expert opinions... |
Side note: one of Apollo Client 2.0 good news is that we can write a vuex implementation of the apollo cache. That may open nice possibilities like getting apollo data directly in getters. |
Yeah I'm eager to use apollo-client 2.0, it has so really nice features. To answer your question from my experience @alidcastano, there is no problem with using vuex + apollo. It just depends on how you use them. If your application uses a REST api, the Gitlab approach is very nice. You query your API, and store data in any format you wish in your store for further use in your application, vuex is not only used as a local app state manager but can also be used as a cache manager. Apollo is made to interact with your graph API. You send a query, the result is normalized by stored in apollo's redux store, is a similar way the Gitlab approach uses vuex for. So apollo (vue-apollo for easier integration) is the tool of choice to interact with your API data, locally and remotely. But you still need a tool to manage your local application state. Sure, components have state and you can pass is down to children components. But sometimes you need transversal data. The is where vuex comes in. For instance you can have a currently selected item id (that comes from apollo) stored in vuex, so that you can request this item via apollo in different components. By default, if a query was already fetched, apollo will use the redux store instead of re-querying it, so don't hesitate to do the same query multiple times. TL;DR: Use vue-apollo to interact with your graph API. Use vuex to manage your local app global state. But you shouldn't duplicate data between vuex and apollo. |
@gijo-varghese What's interesting is that Facebook created the Flux pattern and they also created Graphql... But yea I had a similar feeling that most aspects of Vuex are not necessary given that Apollo 2.0 comes with its own cache/store implementation. As @SebTSo mentioned, Grapql can manage component local and remote state, but you still need a way to manage application state - which is where Vuex getters (or I'll go ahead and close this issue since the gist of the question has been answered but feel free to still add to the discussion. Thanks again guys. |
@alidcastano: The flux pattern and graphql are made to work together. The apollo client implements the flux pattern (because it uses redux, which is derived from flux).
Actually, you shouldn't imo. Apollo should be the only one handling data from API. And vuex/vue-stash shoud only manage your local data (dumb example: a click counter). But sometimes you need to reference API data with vuex. Let's say your app is in logged mode. You often need to access the current user's name for instance. You can store the userId in vuex, but every time you need to access the name, you should to an apollo query in your component. The confusion is caused by th fact that 2 state managment tools are present in the same app. Apollo 2 will be much more intuitive because you'll be able to use vuex for local state and API data. EDIT: Maybe you meant "in sync" with your API data, not in sync between vuex & apollo. That makes my answer unrelevant. But if that's what you meant, you can specify a fetchPolicy for each request so that a network request is done everytime. |
A fullstack example with real world cases would be super helpful or even a video tutorial in Udemy. Otherwise it feels like Vue is falling behind React which has a more mature ecosystem and examples in terms of GraphQL. Ideally there should be an official implementation of Apollo that replaces Vuex |
@lobosan Did you take a look at https://github.com/Akryum/devfest-nantes-2017 ? |
Wouldn't it make sense to drop vuex altogether and put stuff like local session state in apollo client as well? |
@beebase nope. Apollo's job is to interact with a server via the graphql queries (or mutations & subcriptions). It stores that data locally in your app so that you don't have to query the server every time you need some data. To do so, it uses a state management library (redux in apollo-client 1.x) to manage a representation of the data in your app's memory. Most people using vue-apollo already use vuex in their application to manage their app state (usually non-persisted state). So it makes sense to drop redux & tell apollo to store its data in vuex instead. Because you're already using it for your app local state, you don't need 2 state management libraries. |
Using apollo as a client-side state management system is becoming more and more popular, thanks to https://github.com/apollographql/apollo-link-state |
Do you mean like apollo directly writing into vuex state, or apollo triggering vuex actions, that write to vuex state? Either way, with apollo 2.0, you can make local state persistent, control interaction with server, control caching, and it has the same reactivity in components like vuex has. The only thing that's a bit funky, is writing queries inside components as opposed to vuex. It feels like you might end up with duplicate code and I wonder how maintainable this is in very large apps. |
@beebase Write |
@Akryum yes I am, but at the same time that probably only makes sense for queries/mutations being repeated in multiple components? |
@Akryum - do you not recommend to have the GQL inside of each .vue component? Scott |
@smolinari @Akryum me too waiting for an answer for that I've created a separate issue for that #228 |
Is there any update on this? Defining this would help with defining the best practice to link Apollo into Vue + Vuex. I have created a project with just Apollo and Vuex. If it works out fine I'll make a boilerplate. Personally it doesn't make sense to directly write the queries on components. Since these are asynchronous process it could be best handled in actions in Vuex and only the result can be returned to the component. Would help in separation of HTTP request logic. |
This is the concept behind Apollo. Co-locate the data requirements of each component with the component itself, like you do with presentation/logic. Apollo does the rest! The Apollo community is also moving towards apollo-link-state for local client-only data instead of relying on Redux/Vuex/etc. |
For example, I recently wrote a reasonably big app which doesn't need vuex. |
My thoughts were the same and my approach has been to store anything related to apollo in a mixin and then include that in my individual components. For example I have an allFruitQuery mixin that allows me to simply use 'allFruits' in any component by including my mixin `import allFruit from '@/graphql/queries/allFruit.gql' export const allFruitQuery = { |
More of this! Outside of reading code (which is great), I like to read/know the WHY behind it. Any good resources? Tuts? Most of the Apollo or GraphQL tutorials are for React. I've been waiting for one of you Vue/Apollo experts to put something out that I can purchase. :) Just found: https://akryum.github.io/vue-apollo/guide/#what-is-graphql |
Worth mentioning these packages: |
I ended up using Apollo directly, similar to this approach: https://markus.oberlehner.net/blog/combining-graphql-and-vuex/ |
I have been working around various approaches and tried to give a chance to using vue apollo and cache without vuex. I admit the caching woks well but one key aspect i could not solve is to be be able to use cache state in a computed property which we use a lot with vuex getters to react to change of state.
|
FYI also. apollo-link-state has been moved into the Apollo client core, so the idea of getting rid of Redux or Vuex has become a first class citizen. Version 2.5.0 of Apollo Client will include it and the alpha is basically ready for testing now. Scott |
@smolinari , Hi Scott thanks for the feedback, do you know how we can use the state in a computed property. a simple exemple is I am trying to create a computed property to check if a user is logged In. so i created a isLoggedIn typeDefs in my local cache and change its value from false to true when users are logging in and out. but the process to access the cache is asynchronous and the computed property does not provide the reactivity vuex getters provide. is there any easy way to do that with apollo-link-state ? |
When you use the local cache to store whether the user is logged in or not, why do you still need a computed property? Can't you just use a query defined in the apollo object and use result() or update() methods to deal with updates? |
the difference is that you can use a computed property to bind data to the presentation layer very easily. The cache requires you to initiate a query while computed property is updating the UI everytime the value changes. I coudl not find a way to do it so far with the cache. ( but I am a beginner so it may just be ignorance) this is for my poitn of vue a greta value brought by vuex. you can associate a getter to a computed property and bind it to update the UI. every time the state of the store is changed the getter will trigger a change in the computed property which through the binding will impact the UI. so in my exemple it is very easy to show or hide components or DOM elements based on this value. |
Now I understand what you are looking for. Thanks for keeping at the explanations. But, your wish for better readability/ more Vue-like code (from your perspective) will end up an extra layer of abstraction, which only means extra work and added verbosity. That's because in your example, Instead of wanting to grab the central store and have it magically return the data needed, you should think in terms of querying and mutating that store. The queries and mutations themselves are also quite declarative and basically self documenting. Unfortunately If I may ask, what's not "Vue-like" with my Todo app in your opinion? Can you give me some concrete examples where you are going, "this looks really odd to me"? Maybe I can get your mental model changed, so you can see "the Apollo/ GraphQL way" is a very good methodology for state management, both on the server and the client. 😃 Edit: I just looked at my refactored Todo app again and to me it is totally Vue-like. It can't get any more Vue-like. The queries and mutations are within the components where they are needed, they are clear in what is wanted in terms of data and the components are all doing only one thing (aka SRP). Please do try to tell me what you don't understand or don't see as Vue-like. It doesn't get any better than that. 😄 Scott |
Hi Scott, sorry I didn't mean to offend by using "vue-ish"/"vue-like" or trying to be a gatekeeper.
Maybe it wasn't the best idea of renaming it to // ViewProjects.vue
// fictional
...
export default {
...
apollo: {
allProjects: this.$state.projects
},
...
} This file which includes, while hard to read, all the flexibility and goodness of graphql/apollo is squared away and usually almost nobody working on just the vue component needs to looked at it: // ./store/apollo/StoreInterface.js
import ALL_PROJECTS from '@/graphql/project/projectsAll.gql'
const store = new VueApollo.Store({ // inspired by Vuex.Store
state: {
projects: {
get() {
query: ALL_PROJECTS
fetchPolicy: 'network-only'
},
set() { // maybe do some mutation to add a project
}
}
}
As I explained in my first post, what I love most about Vue is the simple and powerful way, where you have one state, a global source of truth from which everything else then reacts and flows. When you then change the state, you do it in an "atomic" way. Atomic not in the sense as used with mutex, but like more a single line of code which you can grasp with one look. Also you can glance over a Vue component in a few screens an get a pretty good idea what's happening. That's what I also find most valuable about SRP approach but of course isn't technically what SRP is about and totally misapprehension of it. So maybe it's better to say I don't care about SRP that much. So for example in your codesandbox.io, I like how you do this: // TodoInput.vue
data() {
return {
todo: '',
addTodo: ADD_TODO
} It's one line of code and I don't really need to know, that there is some graphql stuff going on. it could also be a vuex store or something completely else that manages the state. it's abstracted away, all I see is how to modify my state. I don't care so much that the state gets modified with a SRP approach, so I would put the definition of APP_TODO in a helper/store file, with all the others I would eventually need. this is what I'm trying to do. On the other kind, while glancing over I didn't care much for this: // TodosList.vue
queries: {
getTodos: gql`
{
todos @client {
id
todo
completed
}
}
`
},
} but then I saw that it was used exactly like I explained above here: // TodosList.vue
data() {
return {
todos: this.$options.queries.getTodos
}
}, So my mind immediately got caught by the verbosity and strangeness of having gql code there, inside the component. as much as having all this nested
Totally true. Also in fact, really fine, I want to be able to create all the queries, typDefs and resolver, to be able to wield this power. I just feel, it shouldn't happen onthespot inside a SFC vue component, were it messes up the awesome simplicity of vue's syntax. For me that's more worth then technical correct SRP. because in my mind it's still SRP as long as I see where the component is modifying the state. If this happens via graphql or websockets or localStorage or http request or vuex or vue-stash, that's just an implementation detail. Which in my mind a vue component should not have to care about. Like I said, I think you two guys just have a different philosophy and approach, which is totally fine. I was just looking for someone which maybe wants to help to make it more concise or most ideally already has a best practice how to square everything away in a helper file or store like interface without reinventing the wheel like you said. maybe I will try to use your example as an simple starting point to try to show you what I mean. It feels more approachable then having to clean up my own project first before I can try it out. Thank you for that great jumping point! |
Aha! This mindset needs to change, because the query language is a core strength of GraphQL. Any query defines exactly what is expected to be retrieved from the "store" (actually the Apollo cache). If you want to, you can put your queries in a
Well, I don't think the queries or mutations mess up the Vue syntax. I think it enhances it, a lot! Think about it this way. You are a developer and you want to understand what pieces of state are being brought into the component. Let's say, it's a blog post. And in a blog post, you could just have data () {
return {
blogPost: getSomeBlogPost()
}
... That's what you are looking for right? But, how does one know what is being delivered, what props are there to be "consumed"? The dev would need to go looking at that method and what it does. When the gql query is in the component, the dev knows exactly what data is being "pulled" into the component for instance. Like this: data () {
return {
blogPost: gql`
query singlePost($slug: String!) {
post: Post(slug: $slug) {
id
slug
title
description
image {
url
}
}
}
`
}
... // the rest of the component Now imagine that dev is needing to make a change (and regarding SRP), with the gql query (or mutation) in the component, she would simply go to the component and update it with the new field or fields needed and.... Boom! Those fields are ready to use and the dev just adds the necessary interpolation fields in the template code for rendering. With the function, the dev would have to go do some change somewhere else in code she might not understand. That breaks SRP. 😄 Now think about the dev coming to this component and just wanting to understand it. She will see right off the bat which fields are coming in from the server. And, with the How awesome is that?
No problem. Just don't spend too much time with it trying to fight the flow. 😁 Scott |
Hi Scott, it's true that by getting rid of the query, you have to go hunt for the fields and specifications. that's one downside of it. great thing, with using a global store, there is only one file where it could be and you already know how it's called. But at the same time, when using vuex, I also don't have my API calls where I specify which arguments get passed directly in my SFC. This is why I feel, like I wrote in my first post, that the "final step" of vue-apollo is missing. It feels too barebones to use it in SFC directly. I just modified your example, maybe it's clearer now: https://codesandbox.io/s/k2jyq0np0o You are using But then I saw in For me the style of the component has to flow from the data directly. If a So I created an computed: {
// a computed getter
labelStyle: function() {
// `this` points to the vm instance
return this.todo.completed ? "line-through" : "none";
} The click action now directly changes the state of the todo. It does this via the store and the component writer doesn't need to use any gql for it. methods: {
toggleTodo() {
$state.todo.complete(this.todo,
this.$apollo);
} Of course like I commented it would be even better if it would work directly via But the next thing I will try to work on is to make this possible: methods: {
toggleTodo() {
this.todo.completed = !this.todo.completed;
this.$state.todo.update($this.todo);
} Ideally only updating fields which are changed. Or hopefully vue-apollo is already keeping track of this for me... Obviously |
Um, in a big application, this is NOT a good thing to have. Anything "god-like" is basically a bad coding pattern.
I actually just changed it to a computed property myself too, because the function caused a bug. If you selected the filter for active tasks, and went back to all tasks, the strike-through was missing on the completed tasks. Oops! 😁 And, that code has nothing to do with Apollo usage really. 😃 I see where you are heading and it's also doable, i.e. creating a store for the queries and mutations. But, it's counter-intuitive to me. I mean, Guillaume was doing something similar and has decided to change it to local queries and mutations. I'll bet it's because the code is then easier to reason about and that is what Vue is all about too. 👍 You just have to agree it's the better way to make the SFC comprehensible at first sight. 😉 Scott |
Hi Scott,
But as far as I understand, Vuex also does something like it, were all the "business logic" is at the same place with all the other actions, mutations, etc. And not inside the SFCs...? Maybe when working more with it, I will also get sick of it like @guillaume. We will see.
No biggie, I just mentioned it just because you ask what I don't find "vue-ish" about it. Also while refactoring computed: {
allDone() {
if (this.todos.length === 0) return false;
return !this.todos.some(function(todo) {
return !todo.completed;
});
},
visibleTodos() {
switch (this.listFilter) {
case "SHOW_ALL":
return this.todos;
case "SHOW_COMPLETED":
return this.todos.filter(t => t.completed);
case "SHOW_ACTIVE":
return this.todos.filter(t => !t.completed);
default:
throw new Error("Unknown filter: " + this.listFilter);
}
}, <li v-for="todo in visibleTodos" :key="todo.id"><Todo :todo="todo" /></li>
<p v-if="allDone">You did everything, awesome!</p> |
Sort of. The Vuex store can and should be broken up into modules and can be namespaced. The changes to computed properties are good ones. I'll update my sandbox. Scott |
Of course, this has to be possible with "vue-apollo-store" in the end as well. Like I said, using it should feel like just another flux store, the graphql goodness is just squared away at the store area/namespace/file/folder and not inside the SFC. But this feels huge for somebody like me which has never written a vue-plugin. So if anybody else with more experience in the vue ecosystem feels interested in taking this on, I won't be mad! Just tell me about it! ;) |
Or if somebody want to give me pointers for starters I would be really grateful. I have 2 major roadblock, where I'm not sure about whats best practices or where to even start: First Second Third I may be really cool to make something similar to how Vuex initializes it's state. const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
}
}) So it would be really cool, if this state then could be automatically mixed in with apollo: {
count: gql
} by my plugin? Question is, is mixin the right aproach? Can I even make a mixin for another plugin? If yes, can I just populate |
The changes to computed properties don't work, because the ApolloQuery component seems to have a different scope. So, I have to use methods to get the todos into the scope of the component to manipulate the data. The And you must admit, even with a simple app like this, the amount of additional code you are adding is a lot and it's making what is fairly simple, a lot more complicated and.....all that just so components look a bit "cleaner"? 😉 Scott |
How can you ask for best practices, when what you are wanting to do has never been done? To #2: The Apollo Client (the store) is initialized via the Scott |
Hmm, it just works at my end and I'm still using the same
Of course I'm adding a lot of stuff now, because this "vue-apollo-store" doesn't exist yet, the whole reason I write all this. In the end, once this exist, you should be able to just import & use it like any another plugin with 1-2 lines and then use it like this but with all the graphql/apollo instead of vuex/axios. Maybe like this? const store = new Apollo.Store({
state: {
todos: ALL_TODOS // is just another gql import from a ".gql" like right now
},
mutations: {
addTodo (todo) {
this.$apollo.mutation(ADD_TODO,{todo});
}
}
}) Or it will be a mixin? But it shouldn't be anymore boilerplate like right now, just all in one place (or seperate namespaces if you want)
I mean more like best practices how to interact with other plugins, how to initalize, like I wrote above But I feel like I repeat myself now. Like I said, you don't have to use it, if you don't like the idea. But if somebody else wants to work on it or give me some pointers, please step forward! :-D |
Yeah I saw that. But my question is more, how to write your own plugin, which does something similar. So working from this, it should look something like this for the "enduser" // store.js
import Vue from 'vue'
import VueApollo from 'vue-apollo'
import VueApolloStore from 'vue-apollo-store'
Vue.use(VueApollo)
Vue.use(VueApolloStore)
const state = {
...
}
export default new VueApolloStore({
state
}) // main.js
import apolloStore from "store.js"
const client = new ApolloClient({
clientState: {
defaults,
resolvers,
typeDefs
},
uri: ''
})
const apolloProvider = new VueApollo({
defaultClient: client
})
apolloStore.setProvider({
defaultProvider: apolloProvider
})
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
apolloStore,
render: h => h(App)
}) Question is, how and why does That's what I'm stuck with right now and where I hoped to get some pointers to accelerate this process. But as always, you never can jumpstart reading the docs and browsing the source ;) |
Yeah, because you took out the
There is no boilerplate right now. Your attempts are only adding more abstraction and verbosity to an already finished abstraction, and there is no way you can simplify the Apollo Client / GraphQL API, because you still have to fulfill it to make the intended data retrieval and manipulation work.
It seems to me, you are trying to fit the mental model of Flux architecture into Apollo Client's non-Flux system for state management. You are doing exactly what the Apollo team are trying to overcome, needing two state management systems on the client.
Yeah. The idea is a waste of time and I'm sorry I can't get you to change your mind about it. Scott |
This issue is too long to be useful for someone trying to figure out how to deal with state in a vue + graphql app. So it would be better to maintain a section in the official docs related to this topic or even better docs about vue + graphql in general covering authentication and authorization |
Although the vue-apollo docs (I am assuming that is what you meant with official docs?) are a bit limited and could go into more detail with examples and explanations, there is no topic to cover from this thread in the docs. Or put another way, you don't need Vuex with Apollo Client anymore to run Vue with a GraphQL server. So, there are no best practices when using the two together. It's simply no longer necessary. If you understand Apollo Client along with Apollo link state, then the vue-apollo docs should get you rolling with Vue and Apollo (GraphQL). Scott |
I don't understand what you mean? Why would that make it two state management systems? How I imagine it and showed above, it's more like another interface to access the same state management which gets handled by vue-apollo. It's true that it adds more abstraction, but it doesn't double it, because it still refrencing, reading, mutating the same graphql/apollo-client/apollo-state-link? |
Correct.
Because I'm fairly certain at some point, when we have a large application, your extra layer of abstraction will also need some sort of extra management to make sense of it all. It might not be a state management system, correct, but it will be some sort of (extra/ unnecessary) system. You are also moving the logic for reasoning about state and data control away from the point where it should be controlled. And lastly, you are trying to make a declarative system into a different type of declarative system. This may sound harsh, and I don't want to discourage you or hurt any feelings, but you are solving a problem that is only between your own ears. 😊 Scott |
I'm going to add one more thing to hopefully change your mind @JoeSchr . The query and mutation calls in the components have the ability to "define the shape of the returned result data". In other words, if the developer can see what can be returned from either a GraphQL endpoint or a client resolver, then she can ask (query) for only specific fields of that data. And again, this is another one of the great advantages to GraphQL. It is also that extra verbosity you have an issue with in the component. The query in the component isn't THE query, it's A query for data, but in the specific form the component needs it in (and why it may seem verbose). The Todo app doesn't demonstrate this response structure control, unfortunately. So put another way, your intentions of redefining queries into simpler commands is obscuring this ability and flexibility to define the response structure. For every query needed with a new response structure, and in a big app it could get quite intense, you'd have to come up with a new wrapping function, or even a new DSL, and doing all that is just so you can be at ease with what you are seeing? I get it too. I hate JSX and this is sort of like JSX. But, you are a smart guy. Dream a little and imagine the consequences of your intentions. Please. 😉 Btw, I've updated my Todo app to delete completed tasks too. 😄 https://codesandbox.io/s/k3621oko23 @Akryum - if you consider it worthy (and I'd really like your opinion on it), I'd like to add it to the examples in the docs for client side state. My version of the app was originally Sara Viera's example app. I've just enhanced it some. 😄 Ok? 🙏 Scott |
@smolinari Why not! 😸 |
A valid point, but also just another tradeoff I think one has to take this into considerations with the kind of application they builds. But I would rather have there be a choice than there be no choice at all. For the kind of application I'm doing right now, only querying a subset of the whole dataset is not a usecase that happens often (if at all). On the other hand, the components are already very big and unwieldly, so I really hestitate to make it even more verbose. Further on I have gotten really sick of having all my data queries sprawled all around the place, which really makes bug hunting an issue. This firstly led me to search for a vuex like global state management, where you have a better handling on state management changes via dedicated mutations/actions. That's all more important to the kind of application I'm working on, then having granular control over how much I fetch, because I mostly fetch everything. So my plan right now is to replace all the axios calls with apollo (inside each) component and decide from there if this is good enough or if it still causes the same issues and move some or most into a store like entity. |
Nice, I was thinking of adding that along as well, to get a better feeling for it. But then the strikethrough caught my eye and I decided this was a smaller challenge to try it out |
You are correct! 😄 Just to show you how you can "split it up", check out this fiddle. https://jsfiddle.net/smolinari/65meb0px/ It's using Quasar Framework. This form is only three questions and is a survey, but the whole concept can be scaled to any size form. Also, currently the data is being formed and given in the component. Imagine the form being built automatically, where each input field type does its own mutation. That is incredibly powerful.
Is it a REST API you are using? If yes, this is where GraphQL(done right) is going to blow it out of the water. Front-end developer efficiency both in coding and troubleshooting was one of the reasons why Facebook came up with GraphQL, believe it or not. 😃 Scott |
@Akryum - PR is up! 👍 Scott |
I spent months battling with Vue Apollo (via Nuxt Apollo) and trying to get the Apollo queries/subscriptions to actually be reactive like a Vuex store would be, and all the verbose code you need to write to update the local state after each mutation. I read this thread and I can see that a lot of people feel the same way as I do. I decided to use VuexORM to handle all my data, it took me a few hours to get setup and define my models, and I have to say it is 10x better than using the Apollo Local state. Yes you end up with "two sources of truth" in that you have the Apollo cache/local state, and Vuex, but if one of those sources of truth is a pain in the ass to use, then I'm happy to just ignore it! If anyone is looking for a better way to handle complicated data in their Vue or Nuxt app, this will probably make you life easy! |
I was also thinking of using vuex orm as a local "database" and only using graphql for fetching data from the server that gets normalised into vuex relational tables. I believe there's even a graphql plugin for vuex orm. As tempting as graphql looks, It still feels scary using it with local relational database structures |
I'm not sure what the problem might be which you are having with reactivity. @drewbaker If you update the cache via @client, then the queries that are involved should update too (ie. are reactive). Was it mainly subscriptions being an issue by chance? I can't disagree that the code you need to write to update the cache can get a bit verbose. I was thinking it needs an abstraction like an ORM too and then it would be awesome and most definitely a simplification from having two sources of truth and more importantly, keeping them in sync. I feel using Vuex at all is defeating the whole purpose of a GraphQL client with Vue. You might as well stick with REST. :)
You haven't found the GraphQL paradigm yet. Keep plugin at it! 😁 Shameless plug (pun not intended): Have a look at an article I wrote on the subject. It will either confuse you more or get GraphQL to click for you. Scott |
Thanks Scott. I’ve since replaced Nuxt Apollo with https://www.npmjs.com/package/nuxt-graphql-request and VuexORM (on larger projects) and it works fantastic. |
Hi @Akryum!
Apollo's cache and vuex's store seem to have some overlap in terms of usage, so how would you recommend using vue-apollo and vuex together?
The usual approach with REST would be to have a folder that holds the api service and a folder that holds the state store (this is how Gitlab does it), and then have it all come together inside the main component; another approach is to have the api service/calls integrated into vuex actions.
My first instinct was to use the vanilla apollo plugin and follow one of the above approaches. But then I realized that graphql is a different paradigm - the component queries and mutates its own data - hence why you tightly integrated query fetching inside components. So it'd be great to have the creator of the plugin weigh in on best practices.
Thanks
// This is to related issue #7, so I'll cc people who might be interested in this discussion @PierBover @SebT @RichAyotte @smolinari
The text was updated successfully, but these errors were encountered: