2

In my component I am trying to get the old value and new value of a particular array of objects that is assigned in the vuex store state as followed. However when I newArray and oldArray return the same array of objects.

I understand from the documentation the following but I dont understand what is the best way to retrieve the different versions.

Note: when mutating (rather than replacing) an Object or an Array, the old value will be the same as new value because they reference the same Object/Array. Vue doesn’t keep a copy of the pre-mutate value.

here how I am trying to do it right now in the component

export default {
  name: 'O1_OrderBook',
  watch: {
      '$store.state.orderBookSell': {
         deep: true,
         handler (newArray, oldArray) {
           console.log(newArray,oldArray)
         }
       }
    },
}
matthew
  • 703
  • 2
  • 9
  • 24
  • actually, what are you trying to do in the watcher? could find an easier way if i know what you are trying to achieve – Jacob Goh May 25 '18 at 07:56

2 Answers2

4

let say when you create an array/object in Javascript,

 var arr = [1,2,3];

This creates an array in the browser's memory. But what arr variable contains is not the entire array value, it contains the reference to the array in browser memory. You could think of it as arr contains an address that can point you to the real array value in browser's memory.

if you do

var arr = [1,2,3];
var arr2 = arr;
arr2[0] = 4;
console.log(arr); // you would get [4,2,3];

editing arr2 changed arr too. Because they both point to the same array in browser memory.

That's what "the old value will be the same as the new value because they reference the same Object/Array" means.

The same principle applies to object as well. In Javascript, an array is just a special type of object.


to retrieve the different versions of the array in the watcher, you must clone it to set it as a new array everytime you mutate it.

for e.g.,

state.orderBookSell = [...state.orderBookSell];

BUT..... [...array] is shallow cloning, not deep cloning. And that's a problem. You have an array of objects. Remember that object also have the same rules. They are passed by reference. So you gotta do a deep clone, so that all the objects is cloned as well.

using lodash cloneDeep method for deep cloning

state.orderBookSell = _.cloneDeep(state.orderBookSell);
Jacob Goh
  • 19,800
  • 5
  • 53
  • 73
1

Based on Jacobs answer this is what I re-arranged in my component as to get it to work.

I created a computed variable in the component that deepClones the particular state array of objects.

computed: {
    orders () {
      return _.cloneDeep(this.$store.state.theArray)
    },
  },

and then setup a watch for that computed variable

watch: {
    orders (newValue,oldValue) {
      console.log(newValue,oldValue)
    }
  }
matthew
  • 703
  • 2
  • 9
  • 24