maxxdev
maxxdev

Reputation: 313

Vuejs Vuex state overrides outside store without mutation or direct access to state

State of Vuex overrides in the map()

Expecting beahavior - count always 1 when click to the Trigger button

Current behavior is count is encreasing each time when click to the Trigger button and if we take a look on a console log we can see that getter returns mutated state

const store = new Vuex.Store({
    state: {
        stuff: [{
            count: 0
        }]
    },
    mutations: {},
    getters: {
        stuff: s => s.stuff,
    }
})

new Vue({
    el: '#vue',
    store,
    data() {
        return {
            res: []
        }
    },
    methods: {
        trigger() {
            const stuff = this.$store.getters.stuff
            console.log(stuff)
            const res = stuff.map(p => {
                p.count += 1
                return {
                    ...p
                }
            })
            this.res = res
        }
    },
})
 <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>  <script src="https://unpkg.com/[email protected]/dist/vuex.js"></script>
 <div id="vue">
  <div>
   <button @click=trigger()>Trigger</button>
   <pre>{{res}}</pre>
  </div>
 </div>

Upvotes: 0

Views: 553

Answers (1)

Michal Lev&#253;
Michal Lev&#253;

Reputation: 37753

This is expected. Vuex is just a library inside JS virtual machine - the rules of JS applies...

Value vs. Reference

  1. const stuff = this.$store.getters.stuff - stuff is now a reference to an existing object (array in this case)
  2. stuff.map() iterates the array passing each item as p parameter. If the p is an Object, p is the reference to an object inside Vuex - if you modify it, you are modifying the object inside the Vuex store

This is bad and to be sure and safe, you can set Vuex to throw an error anytime data inside Vuex are modified without using mutation

const store = new Vuex.Store({
  // ...
  strict: process.env.NODE_ENV !== 'production'
})

Upvotes: 1

Related Questions