bekwam courses

Vue.js Vuex Watch State

June 20, 2020

This article demonstrates how to watch for changes in a Vuex state variable. A Vue Watch is set up on on an expression that involves the state variable. When that variable changes, the associated handler is called. I also use the Watcher to provide an initial value. The Watcher is called when first initialized, before the app mutates the Vuex state.

This CodePen will increment a Vuex counter state variable when a button is pressed. The button commits a mutation. The value displayed with the "The current value is" tag is coming from a data field local to the component. That data field will be updated when the Vuex state changes. Purposefully, the data field is initialized to null. The initial value is provided to the page by the Vuex state variable.

See the Pen Vuex Watch State by Carl Walker (@walkerca) on CodePen.

This screenshot shows the two UI elements involving Vuex: a button issuing a commit and a tag displaying the local data field. Pressing "Increment" calls the mutation "INCR" which sets a state variable "counter". There is a Watcher on counter that updates myprop. myprop is displayed in the tag.

Annotated Screenshot of CodePen
Button Invokes Mutation that Indirectly Updates Data Field

This is the code for the Vuex store. There is a single state variable and mutation.


const store = new Vuex.Store({
  state: {
    counter: 0
  },
  mutations: {
    INCR: (state) => state.counter++
  }
});

The button template code registers a click handler.


// template section
<button class="button is-success" @click="incr">Increment</button>
  
// script
methods: {
    incr() {
      this.$store.commit("INCR");
    }
}

The value if myprop is displayed using handlebars.


// template section
<span class="tag is-success">
   {{ myprop }}
</span>

// script
data: {
    myprop: null // no attempt at defining initial state
}

The Watcher is the mechanism that synchrhonizes the data field and the Vuex state variable. I'm using a nested expression that references the store directly. The Watcher does not have to be on a local data field or computed which reduces trivial code. Also, notice the immediate property. This provides an initial value of "0" instead of the null that's assigned to myprop. That is, before the value changes, the Watcher is called.


watch: {
    "$store.state.counter": {
      handler: function(nv) {
        this.myprop = nv;
      },
      immediate: true // provides initial (not changed yet) state
    }
}

There are a few other forms of Watcher you might encounter. If you don't care about the immediate property, you can use the following shorter syntax.


// ALTERNATE SYNTAX #1
watch: {
  "$store.state.counter"(nv) {
      this.myprop = nv;
  }
}

You can also dispense with the expression and watch a function that is a computed.


// ALTERNATE SYNTAX #2
computed: {
  ctr() { return this.$store.state.counter; }
},
watch: {
  ctr(nv) {
      this.myprop = nv;
  }
}

This article showed how to register a Watcher that responds to changes in Vuex state. Often on the Vue Land Discord, I see questions about how to take an action in response to Vuex changes. This is preferred over mechanisms like an Event Bus since you have the listener mechanism already established. Whichever syntax you follow, you'll be able to keep your component aware of your Vuex changes.


Headshot of Carl Walker

By Carl Walker

President and Principal Consultant of Bekwam, Inc