1
votes

Suppose I'm using an external API which works with Machine objects. You can create a Machine with createMachine, which will give you a complex object with several nested properties, and a set of functions to alter state on that object. The API provides for example: loadMemory, sleep, connectDevice. (Imagine anything similar, this is just an example).

I want to mantain a global Vuex Machine object, so I've an action to dispatch that initial creation and store the returned object just like:

actions: {
createChannel({ commit, state }, params) {
      m.createMachine(params).then(
        function (newMachine) {
          commit('setMachine', newMachine);
        }
      ).catch(err => { console.error("Error"); } )
    }
}

The mutation is pretty straightforward in this case:

  setMachine(state, machine) {
      state.machine = machine;
    }

Now that API set for the "Machine" objects, as we know has a bunch of state-modifying calls -we don't know what specific fields they change-. As they modify state, and I want to use them to affect the global Machine object in the Vuex store, I would like to wrap them in actions.

An action could call

this.state.machine.loadMemory(mem.addr)

But if this call itself modified the machine object, how do I commit the new state? Should I clone the old object, apply the state-changing method and replace the object ?

I know cloning is not an easy task.

Thanks.

2

2 Answers

1
votes

You can re-mount your complex object. According to the example, the mutation could be:

loadMemory(state, newAddr) {
  const { machine } = state;

  state.machine = {
    ...machine, // set all machine's properties
    addr: newAddr,
  };
}

It works in any level of nested objects you want. Another example:

loadMemory(state, newValue) {
  const { machine } = state;
  const { machineObjProp } = machine; 

  state.machine = {
    ...machine, // set all machine's properties
    machineObjProp: {
       ...machineObjProp, // set all machineObjProp's properties
       value: newValue,
    },
  };
}
1
votes

One way is using lodash cloneDeep, it will copy app properties and methods of object

import _ from lodash

this.state.machine.loadMemory(mem.addr)
const copyMachine = _.cloneDeep(this.state.machine)
this.$store.commit('setMachine', copyMachine)