Reputation: 4730
So I have a Vuex store with a few variables, it looks something like this:
var dataStore = new Vuex.Store({
state: {
consumer_id: undefined,
some_other_data: 0
},
mutations: {
update: function(type, payload) {
state = Object.assign(type, payload);
}
}
});
And I have two components, both of which are top level Vue components. However MultiSim
surrounds Sim
. They both use the following method to access consumer_id
:
consumer_id: {
get: function () {
return this.$store.state.consumer_id;
},
set: function (value) {
this.$store.commit('update', {consumer_id: value});
}
},
The issue is that while changes to consumer_id
are propagated to Sim
, MultiSim
only ever sees undefined
(the default value). MultiSim
changes consumer_id
, and this is captured correctly by all three components, but if Sim
changes, MultiSim
does not update.
For example:
MultiSim
sets consumer_id = 10
. [MultiSim: 10, Sim: 10, Store: 10]
Sim
sets consumer_id = 5
.[MultiSim: 10, Sim: 5, Store: 5]
Can anyone see where I might have gone wrong? Is there a way to force an update to all components?
Edit:
So I've found a solution, but it's more of a hack than anything:
MultiSim
sets consumer_id = 10
. [MultiSim: 10, Sim: 10, Store: 10]
Sim
sets consumer_id = 5
.Essentially, the computed method of MultiSim
is not updating, even though it can access the actual stored value just fine.
Upvotes: 0
Views: 399
Reputation: 82489
Assuming all of your properties on state are initialized when you create the store, you could send a generic payload to your update mutation using an approach like this:
const store = new Vuex.Store({
state: {
consumer_id: undefined,
some_other_data: 0
},
mutations: {
update: function(state, payload) {
for ([key, value] of Object.entries(payload))
state[key] = value
}
}
})
This will allow your update
mutation to be generic and set the properties on state.
Here is an example.
console.clear()
const store = new Vuex.Store({
state: {
consumer_id: undefined,
some_other_data: 0
},
mutations: {
update: function(state, payload) {
for ([key, value] of Object.entries(payload))
state[key] = value
}
}
})
const Sim = {
template: `
<div>
Sim <input v-model="consumer_id"> {{consumer_id}}
</div>
`,
computed:{
consumer_id: {
get: function () {
return this.$store.state.consumer_id;
},
set: function (value) {
this.$store.commit('update', {consumer_id: value});
}
},
}
}
const MultiSim = {
template: `
<div>
MultiSim <input v-model="consumer_id"> {{consumer_id}}
</div>
`,
computed:{
consumer_id: {
get: function () {
return this.$store.state.consumer_id;
},
set: function (value) {
this.$store.commit('update', {consumer_id: value});
}
},
}
}
new Vue({
el: "#app",
store,
components: {Sim, MultiSim}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vuex/3.0.1/vuex.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
<sim></sim>
<multi-sim></multi-sim>
</div>
If the properties are not initialized on the state when the store is created, then you will need to use Vue.set.
const store = new Vuex.Store({
state: {
},
mutations: {
update: function(state, payload) {
for ([key, value] of Object.entries(payload))
Vue.set(state, key, value)
}
}
})
Also, both of these presume that you are creating the payload in every case like you do in your computed set.
Note: Object.entries is not supported in IE, so you may need to resort to Object.keys instead.
Upvotes: 1