Please how may we delete items by key in a Vuex state object and still have computed properties bound to getters automatically update?
I have a simple store:
const state {
users: {} // object of objects keyed by userid
}
const getters {
admins: state => Object.values(state.users).filter(o => o.role === 'administrator'),
managers: state => Object.values(state.users).filter(o => o.role === 'manager'),
counters: state => Object.values(state.users).filter(o => o.role === 'counter'),
}
const mutations {
DELETE_USER (state, userid) {
delete state.users[userid] // the user id deleted, i can verify this in dev-tools
}
}
The user is deleted, i can verify this in vue dev-tools, but the computed properties in my vue component do not see the updates:
...
computed: {
admins: this.$store.getters('admins'),
managers: this.$store.getters('managers'),
counters: this.$store.getters('counters')
},
As others have stated in the comments, Vue cannot detect addition of properties or deletion of properties if you use just
obj.newProperty = 1
orobj['newProperty'] = 1
ordelete obj.unwantedProperty
. You need to useVue.set
andVue.delete
as described here https://vuejs.org/v2/api/#Vue-setThe reason is, when you modify an object's existing property by changing its value, you make the modification through the property's setter method, and in the setter method, Vue will notify all things (components, computed properties and so on) that "depends on" this property, to update themselves.
For instance, if you have
vm.a = 1
and you have a computed property calledb
andb
is evaluated likevm.a + 1
, then we sayb
depends ona
as it needsa
to come up with its value. When you changea
likevm.a = 2
, you implicitly invoke a's setter methods, and this method will notifyb
to update.However, if you remove a property (without using
Vue.delete
), you are not calling its setters, and this properties dependencies will not get notified, therefore they wont update themselves.Some extra stories - How does Vue knows what depends on what? Using our previous example, when Vue initialize, it will create getters and setters for its data. In this case, it creates getters and setters for
vm.a
. Vue then tries to evaluateb
, and remember,b
isvm.a + 1
. Duringb
's evaluation, we will callvm.a
, and in fact, we are callingvm.a
's getter method. And inside this getter method, we know thatb
's evaluation relies onvm.a
and we registerb
asa
's dependency.Vuex provides an helper
mapGetters
: (https://vuex.vuejs.org/guide/getters.html#the-mapgetters-helper)This helper can be used into computed field of Vue Component, like this:
After that you can use it like a computed in your HTML template:
or in the component script:
It's directly connected to the Vuex's store, so the created computed is reactive when the store is update.