DatsunBing
DatsunBing

Reputation: 9076

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.

Upvotes: 3

Views: 2198

Answers (1)

IVO GELOV
IVO GELOV

Reputation: 14289

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;
  }
}

Upvotes: 3

Related Questions