Vuex: detect object changes in the state

Created on 29 May 2018  路  2Comments  路  Source: vuejs/vuex

What problem does this feature solve?

This code will not work:

state = {
  ...state,
  count: state.count   1
};

the components will not detect the updated state, and therefore, any computed property called will not render the new updated state.

This will work:

state.count  = 1;

however, they are doing the same thing, so after this feature has been implemented, we can just do this:

updatedData (state, newState) {
  state = {
    ...newState
  };
}

also instead of directly manipulating the state on the mutation handler, why don't we ask the users to return the new state on the handler and let vue do the mutation? So the code above would turn into:

updatedData (state, newState) {
  return {
    ...newState
  };
}

What does the proposed API look like?

On the component
import { mapActions } from 'vuex';

export default {
  name: 'app',
  mounted () {
    this.fetchData();
  },
  methods: {
    ...mapActions([ 'fetchData' ])
  }
};
On the actions
import Axios from 'axios';

export default {
  fetchData ({ commit }) {
    commit('requestPending');

    const endPoint = 'https://somewhere.com/api/data;
    Axios.get(endPoint)
      .then(({ data }) => {
        commit('updatedData', data.ResponseData);
      });
  }
};
on the mutation handler
export default {
  requestPending (state) {
    return {
      ...state,
      request: {
        pending: true
      }
    };
  },
  updatedData (state, newState) {
    return {
      ...state,
      ...newState,
      request: {
        pending: false
      }
    };
  }
};

Most helpful comment

This code will not work:

state = {
  ...state,
  count: state.count   1
};

because all it does it reassign a local variable. That technically can't change the state. That'S just how Javascript works.

This will work:
state.count = 1;

...because it's mutating the state, like it'S intended.

however, they are doing the same thing

No, they are not. One is mutting the state, taking advantage of Vue's reactivity system, the other is replacing the whole state with a new object (or rather, if would if it were technically possible), which would have to be made reactive again, a whole load of wtachers would potentially be fired needlessly and so on.

so after this feature has been implemented, we can just do this:

updatedData (state, newState) {
  state = {
    ...newState
  };
}

Again, this particular code can't change the state, you are only reassigning a local variable. This can never work in Javascript

why don't we ask the users to return the new state on the handler and let vue do the mutation? So the code above would turn into:

updatedData (state, newState) {
  return {
    ...newState
  };
}

Because, Vuex is not redux. Vue's Reactivity system relies on mutating existing state, not creating new, immutable state.

If you want to work with immutable state, vuex is the wrong library for you.

All 2 comments

This code will not work:

state = {
  ...state,
  count: state.count   1
};

because all it does it reassign a local variable. That technically can't change the state. That'S just how Javascript works.

This will work:
state.count = 1;

...because it's mutating the state, like it'S intended.

however, they are doing the same thing

No, they are not. One is mutting the state, taking advantage of Vue's reactivity system, the other is replacing the whole state with a new object (or rather, if would if it were technically possible), which would have to be made reactive again, a whole load of wtachers would potentially be fired needlessly and so on.

so after this feature has been implemented, we can just do this:

updatedData (state, newState) {
  state = {
    ...newState
  };
}

Again, this particular code can't change the state, you are only reassigning a local variable. This can never work in Javascript

why don't we ask the users to return the new state on the handler and let vue do the mutation? So the code above would turn into:

updatedData (state, newState) {
  return {
    ...newState
  };
}

Because, Vuex is not redux. Vue's Reactivity system relies on mutating existing state, not creating new, immutable state.

If you want to work with immutable state, vuex is the wrong library for you.

I will close this as there have been no further arguments been brought forward.

Was this page helpful?
0 / 5 - 0 ratings