1
votes

Environment
We have a Vue Cli using Vue 2. Vuex and TypeScript are installed

Issue
Currently we're getting some vuex state data (via a vuex getter). Then working with it. However, if we mutate the "gotten data" it affects the vuex state. It seems crazy! Here's a very silly stripped down version of a services module:

// vuex
import { mapState } from 'vuex'
// store
import store from './../store';
// types
import { ServiceType } from './../types/services'

export default class TestService implements ServiceType {

  serviceFunction(someArray: Array<number>) {

    // this will return some nested/multidimensional data:
    // [
    //   { prop: [[1, 2, 3, 4]] }
    // ]
    let data = store.getters['getTestStoreData'] 
      
      data[0].prop[0] = someArray          // doesn't mutate the state 
      data[0].prop = [someArray]           // mutates the state
      data[0].prop.splice(0, 1, someArray) // mutates the state
  }
}

The very very stripped down getter looks something like this:

getTestStoreData(state) { return state.data }

So 2 of the 3 above will mutate the store, since they mutate the data variable... Which leads me to believe the getter passes a reference of the state data.

Anyone have insight into this? Or know a good way to handle it? I've got some ideas about passing just the nested data from the store. This stackoverflow answer is some of the best insight I've found.

1

1 Answers

1
votes

In your case you need to clone the multidimensional array. There are 2 types of array cloning: shallow & deep. Shallow copies only cover the 1st level of the array and the rest are referenced. If you want a true copy of nested arrays, you’ll need a deep clone. For deep clones, go with the JSON way OR better yet use Lodash

// Using JavaScript
let data = JSON.parse(JSON.stringify(store.getters['getTestStoreData']));

Or

// Using Lodash
let data = _.cloneDeep(store.getters['getTestStoreData']);

To test out the Lodash clone and clonedeep functions, you will need to install Lodash first:

npm install --save lodash

Or

yarn add lodash

With lodash now installed, use the require() function to now access all the functions that Lodash has too offer:

// vuex
import { mapState } from 'vuex'
// store
import store from './../store';
// types
import { ServiceType } from './../types/services'

const _ = require('lodash'); // Line to be included

export default class TestService implements ServiceType {
 .........