Vue: Why is this computed property not reactive?

Here is a computed getter and setter from a vue component:

paidStartHours : {
    get() {
        return moment(this.position.paid_start, global.DB_DATETIME).format('HH');
    },
    set(value) {
        this.$store.commit({
            type : 'updatePaidStartHours',
            newValue : value,
            position : this.position
        });
    }
}

On get, it returns the hours (HH) from position.paid_start. On set, it commits a store mutation, which essentially recreates the time string for position.paid_start.

In is bound (two-way) to an input as follows:

<input v-model="paidStartHours" type="text">

On initial load, computed property paidStartHours is correct (per Vue Tools).

When I update the input however, the value of paidStartHours does not change. I know that the commit is successful, because the props that are handed to the component are correct. It makes no sense to me.

EDIT:

The code in the updatePaidStartHours mutation has changed a number of times. For example, I tried this:

updatePaidStartHours(state, payload) {
    payload.position.paid_start = 999;
}

The value of the passed prop changed to 999, however the value of the computed prop remained the same.

EDIT II:

I don't think it is worth trying to resolve this issue because I think my whole Vue / Webpack / Node installation is very sick. For example, this morning I delightedly followed this answer, Vuejs and Webpack: Why is store undefined in child components, to import an instantiated store into my App. It all seemed fine but after about 8 hours of stuffing about I see that NO store properties are reactive. I reverted to importing the config only, and now most of my store properties are reactive, but sadly not the ones above. I think I need to abandon the approach until I get time to revisit blow away my Vue / Webpack / Node install and start again.

1 answer

  • answered 2018-07-11 10:04 IVO GELOV

    Vuex mutations should be called from Vuex actions only - so in your code you should dispatch an action, not a mutation. Also, your mutation function is expected to mutate the store argument - not the payload one. Your getter is also wrong - it should use this.$store.getters and not your local component data.

    paidStartHours : {
        get() {
            return moment(this.$store.getters.position.paid_start, global.DB_DATETIME).format('HH');
        },
        set(value) {
            this.$store.dispatch('updatePaidStartHours',value);
        }
    }
    

    Vuex module:

    // initial state
    const state = {
      position:
      {
        paid_start: null
      }
    };
    
    // getters
    const getters = {
      position: (state) => state.position
    }
    
    // actions
    const actions = {
      updatePaidStartHours ({commit}, payload)
      {
        commit('SET_START_HOURS', payload);
      }
    }
    
    // mutations
    const mutations = {
      SET_START_HOURS (state, payload)
      {
        state.position.paid_start = payload;
      }
    }