1

I have a vue store which has the following

store.js

import Vue from 'vue'
import Vuex from 'vuex'

const state = {
      supplementStore: {}
    }

const actions = {
  getDataFromApi ({dispatch, commit}) {
    APIrunning.then(response => {
      commit('SET_SUPPLEMENT', response)
    })
  }
}

const mutations = {
  SET_SUPPLEMENT (state, data) {
    state.supplementStore= data
  }
}

const foodstore = {
  namespaced: true,
  state,
  actions,
  mutations
}

Vue.use(Vuex)

export default new Vuex.Store({
  modules: {
    foodstore
  }
})

My vue component looks like this

Supp.vue

<template>
    <input type="checkbox" v-model="supps.logged">
</template>

<script>
import {mapState, mapActions} from 'vuex'
import store from './store'

export default {
  data () {
    return {
      supps: []
    }
  },
  mounted () {
    this.supps = this.supplementStore
  },
  computed: {
    ...mapState('foodstore', ['supplementStore'])
  }
}
</script>

As you can see I have a component level state called supps which is assigned the value of supplementStore (which is a vuex state) as soon as it is mounted.

mounted () {
  this.supps = this.supplementStore
},

supplementStore gets its value from the the API and it is a JSON object which looks like this

supplementStore = {
  logged: true
}

Therefore, when my Supp.vue component is mounted my local state supps will become

supps = {
    logged: true
  }

supps is binded to an input field of type checkbox (Supp.vue) using the v-model directive.

What I want to achieve:

When I toggle the checkbox, supps.logged should toggle between true and false but, supplementStore.logged should remain unchanged (since I have not binded it to my input field).

What I observe in my Vue Devtools:

When I toggle the checkbox, both supps.logged AND supplementStore.logged are toggling in sync i.e both of them are toggling in sync between true and false, whereas I want only supps.logged to get toggled.

Can anyone help me?

Keith M
  • 421
  • 1
  • 8
  • 18

3 Answers3

2

In Javascript, object is passed by reference. (This is a reasonably good explanation => https://medium.com/nodesimplified/javascript-pass-by-value-and-pass-by-reference-in-javascript-fcf10305aa9c)

To avoid this problem, you can clone the object when assigning to supps.

mounted () {
  this.supps = { ...this.supplementStore } // cloning the object using Javascript Spread syntax
},
Jacob Goh
  • 19,800
  • 5
  • 53
  • 73
  • the solution you provided does not seems to work. `supplementStore ` still changes – Keith M May 11 '19 at 09:46
  • I do, but the actual code belongs to my employer, hence can't share it here. I think the problem is that `supplementStore ` in my actual code is an array of objects `[ { "logged": true }, { "logged": false } ]` and I'm looping the input checkbox field inside a v-for directive – Keith M May 11 '19 at 10:44
1

Have you tried Object.assign instead? In JS objects are passed by reference. Assigning one to a variable will cause the original one to change if the variable is changed inside.

To clone an object, you may try this:

// this.assignedObj = new object. 
// this.obj = original object.
this.assignedObj = Object.assign({}, this.obj);

JSFiddle: https://jsfiddle.net/mr7x4yn0/

Edit: As you can see from the demo, Vue.set or this.$set will not work for you (probably).

Yousof K.
  • 1,374
  • 13
  • 23
0

The data I was receiving from the API into supplementStore was in the form of an array of objects:

supplementStore =  [
    {
        "logged": true
    },
    {
        "logged": false
    }
]

And as Jacob Goh and Yousof K. mentioned in their respective answers that objects and arrays get passed by reference in javascript, I decided to use the following code to assign the value of supplementStore to supps inside my mounted() hook:

mounted () {
    let arr = []
      for (let i = 0; i < this.supplementStore.length; i++) {
        let obj = Object.assign({}, this.supplementStore[i])
        arr.push(obj)
      }
      this.supps = arr

  }

Now when I toggle my checkbox, supplementStore.logged remains unchanged while supps.logged toggles between true and false just the way I wanted.

Keith M
  • 421
  • 1
  • 8
  • 18