Search code examples
vue.jsvuejs2vuex

Updating getter value Vuex store when state changes


I'm trying to figure out how to properly update a getter value when some other variable from VueX changes/updates. Currently I'm using this way in a component to update:

watch: {
   dates () {
     this.$set(this.linedata[0].chartOptions.xAxis,"categories",this.dates)
   }
}

So my getter linedata should be updated with dates value whenever dates changes. dates is state variable from VueX store. The thing is with this method the value won't be properly updated when I changed route/go to different components. So I think it's better to do this kind of thing using the VueX store.

dates is updated with an API call, so I use an action to update it. So the question is how can I do such an update from the VueX store?

EDIT:

I tried moving this to VueX:

async loadData({ commit }) {
      let response = await Api().get("/cpu");
      commit("SET_DATA", {
       this.linedata[0].chartOptions.xAxis,"categories": response.data.dates1,
this.linedata[1].chartOptions.xAxis,"categories": response.data.dates2
      });
    }

 SET_DATA(state, payload) {
      state = Object.assign(state, payload);
    }

But the above does not work, as I cannot set nested object in action this way...


Solution

  • Getters are generally for getting, not setting. They are like computed for Vuex, which return calculated data. They update automatically when reactive contents change. So it's probably best to rethink the design so that only state needs to be updated. Either way, Vuex should be updated only with actions/mutations

    Given your example and the info from all your comments, using linedata as state, your action and mutation would look something like this:

    actions: {
      async loadData({ commit }) {
        let response = await Api().get("/cpu");
        commit('SET_DATA', response.data.dates);
      }
    }
    
    mutations: {
      SET_DATA(state, dates) {
        Vue.set(state.linedata[0].chartOptions.xAxis, 'categories', dates[0]);
        Vue.set(state.linedata[1].chartOptions.xAxis, 'categories', dates[1]);
      }
    }
    

    Which you could call, in the component for example, like:

    this.$store.dispatch('loadData');
    

    Using Vue.set is necessary for change detection in this case and requires the following import:

    import Vue from 'vue';
    

    Theoretically, there should be a better way to design your backend API so that you can just set state.linedata = payload in the mutation, but this will work with what you have.