Shawn Wildermuth

Changing Nested State in Vuex


I've been updating the Atlanta Code Camp website to improve our administration workflow. With the Call for Speakers coming up soon, I wanted to make sure we had a good way of picking only the best talks.

One of the things I've done is move it to a Single App with Vuex at the center of it. But I ran into an oddity with Vuex that I thought I'd share.

Much of the work I do in Vuex has to do with adding, updating and removing objects from the state. That works exactly the way I would expect. For example, I have a lot of mutations that looks like this:

export default {
  setCamps(state, camps) { state.camps = camps },
  setCurrentCamp(state, camp) { state.currentCamp = camp; },
  setBusy(state) { state.isBusy = true; },
  clearBusy(state) { state.isBusy = false; }
};

These are simple mutations, but I also needed to change some flags on objects. This is where it got confusing. When I did what I thought was obvious, it didn't reflect my changes (e.g. didn't react):

  setTalkApproved(state, talk, value) {
    talk.approved = value;
  }

Even though I wasn't setting the value using the state (only changing a value on the property of an object on the state, in this case inside a collection), it didn't work. It didn't work for a couple of reasons. First the value was always false (because nothing was passed for the 'value'). Secondly, Vuex wasn't aware what object I was changing.

Digging in I saw the error of my ways:

  setTalkApproved(state, {talk, value }) {
    talk.approved = value;
  },

The change is subtle, but by passing in an object that contained both the object to be changed and the value, Vuex knew to make the change in a stateful way. This can work for more than just two objects, but I wanted to share how I was able to change nested state. Hope it helps you when this happens to you.