Search code examples
vue.jsvuexvuejs3vue-composition-api

Vue3 composition API watch store value


I want to detect changes in a Vuex state value by watching it in a Vue component. I am currently using Vue 3 with the composition API. I've tried the following approach:

setup(props) {
   const store = useStore();

   watch(store.getters.myvalue, function() {
      console.log('value changes detected');
   });

   return {
      myvalue: computed(() => store.getters.myvalue)
   }
},

But the console.log() will not be called when myvalue is changed.


Solution

  • I think you might need to pass a function that returns myValue getter instead of passing the myValue getter.

    Like so:

    setup(props) {
       const store = useStore();
    
       watch(() => store.getters.myvalue, function() {
          console.log('value changes detected');
       });
    
       return {
          myvalue: computed(() => store.getters.myvalue)
       }
    },
    

    Here is a working example:

    const store = Vuex.createStore({
      state() {
        return {
          count: 0
        }
      },
      getters: {
        count(state) {
          return state.count
        }
      },
      mutations: {
        increment(state) {
          state.count++
        }
      }
    });
    
    const app = Vue.createApp({
      setup() {
        const store = Vuex.useStore();
    
        Vue.watch(() => store.getters.count, function() {
          console.log('value changes detected');
        });
    
        store.watch((state, getters) => getters.count, () => {
          console.log('value changes detected via vuex watch');
        })
    
        return {
          myvalue: Vue.computed(() => store.getters.count),
          change: ()=>{store.commit('increment')}
        }
      }
    });
    
    app.use(store);
    
    app.mount("#app");
    <script src="https://unpkg.com/[email protected]/dist/vue.global.prod.js"></script>
    <script src="https://unpkg.com/[email protected]/dist/vuex.global.js"></script>
    
    <div id="app">
      <button @click="change">💎</button>
      {{myvalue}}
    </div>

    However there are more Vuex-specific ways to do this such as using Vuex watch (or subscribe). Link for examples and more details: Watch for Vuex State changes!