2
votes

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')
  },
2
Vue cannot detect adding or removing properties from an object. You'll need to use Vue.deletethanksd

2 Answers

3
votes

As others have stated in the comments, Vue cannot detect addition of properties or deletion of properties if you use just obj.newProperty = 1 or obj['newProperty'] = 1 or delete obj.unwantedProperty. You need to use Vue.set and Vue.delete as described here https://vuejs.org/v2/api/#Vue-set

The 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 called b and b is evaluated like vm.a + 1, then we say b depends on a as it needs a to come up with its value. When you change a like vm.a = 2, you implicitly invoke a's setter methods, and this method will notify b 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 evaluate b, and remember, b is vm.a + 1. During b's evaluation, we will call vm.a, and in fact, we are calling vm.a's getter method. And inside this getter method, we know that b's evaluation relies on vm.a and we register b as a's dependency.

0
votes

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:

computed: {
  ...mapGetters([
     'admins',
     'managers',
     'counters'
  ])
}

After that you can use it like a computed in your HTML template:

{{ admins }}

or in the component script:

this.admins

It's directly connected to the Vuex's store, so the created computed is reactive when the store is update.