Search code examples
vue.jsvuex

computed properties bound to getters are not updating on deleting items by key from a Vuex state object


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')
  },

Solution

  • 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://v2.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.