Reputation: 1366
I have a vuex store. on change of state preference in the vuex store. i want to rerender the DOM. i want the checkValue method to be called everytime the state preference in the vuex store changes.
index.html
<div id="app">
<my-component></my-component>
<my-other-component></my-other-component>
</div>
vue is initialised, and also store is imported here
my_component.js
Vue.component('my-component',require('./MyComponent.vue'));
import store from "./store.js"
Vue.component('my-other-component',require('./MyOtherComponent.vue'));
import store from "./store.js"
new Vue({
el : "#app",
data : {},
store,
method : {},
})
component where DOM needs to be change on change of the state preference in store
MyComponent.vue
<template>
<div v-for="object in objects" v-if="checkValue(object)">
<p>hello</p>
</div>
</template>
<script>
methods : {
checkValue : function(object) {
if(this.preference) {
// perform some logic on preference
// logic results true or false
// return the result
}
}
},
computed : {
preference : function() {
return this.$store.getters.getPreference;
}
}
</script>
Vuex store file
store.js
const store = new Vuex.Store({
state : {
preferenceList : {components : {}},
},
getters : {
getPreference : state => {
return state.preferenceList;
}
},
mutations : {
setPreference : (state, payload) {
state.preference['component'] = {object_id : payload.object_id}
}
}
component from where the vuex store is updated on clicking in the li element.
MyOtherComponent.vue
<div>
<li v-for="component in components" @click="componentClicked(object)">
</li>
</div>
<script type="text/javascript">
methods : {
componentClicked : function(object) {
let payload = {};
payload.object_id = object.id;
this.$store.commit('setPreference', payload);
}
}
</script>
Upvotes: 16
Views: 37390
Reputation: 1912
I think your main issue is your mutation: VueJS creates everything it needs for reactivity during initialization, so your state.components
object is already initialized when you try to override it with a new object with your mutation payload, which will then not be configured for reactivity (see https://v2.vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats).
Try changing your mutations to:
mutations: {
setPreference (state, payload) {
Vue.set(state.preferenceList.components, 'object_id', payload.object_id);
}
}
Upvotes: 1
Reputation: 17930
Methods are not reactive,
which means they will not track changes and re-run when something changes. That's what you have computed for.
So it means you need to use a computed to calculate what you need, but computed does not accept parameters and you need the object, so the solution is to create another component that accepts the object as a property and then perform the logic there:
MyOtherComponent.vue:
<template>
<div v-if="checkValue">
<p>hello</p>
</div>
</template>
<script>
props:['object','preference']
computed : {
checkValue : function() {
if(this.preference) {
// perform some logic on preference
// logic results true or false
return true
}
return false
}
}
</script>
And then in the original component:
<template>
<my-other-component v-for="object in objects" :object="object" :preference="preference">
<p>hello</p>
</my-other-component>
</template>
Upvotes: 9
Reputation: 28982
v-if
should not contain a function call. Just the existence of the function will likely cause the v-if
to always be true. v-if
should test a variable or a computed property, and it should have a name that's a noun, not a verb ! If checkValue just proxies preference, why do you need it. Why not just v-if="preference"
?
Upvotes: 2