Search code examples
ajaxvue.jsactionvuex

Call mutation before every action Vuex


Vuex allows us to write plugins that do something whenever a mutation is committed. Is there any way to have a similar functionality, but with actions?

I notice you can "enhance" actions like the vuexfire library does, is this the best way to do so?

My goal is to have some way to track if/how many ajax calls are currently pending, and automatically show some kind of animation based on that number.

Edit: To clarify, I am wondering if there is a way to do this using just Vuex, without pulling into additional libraries.


Solution

  • As of Vuex v2.5 you can call subscribeAction to register a callback function which will be called after each dispatched action in the store.

    The callback will receive an action descriptor (object with type and payload properties) as its first argument and the store's state as the second argument.

    The documentation for this is on the Vuex API Reference page.

    For example:

    const store = new Vuex.Store({
      plugins: [(store) => {
        store.subscribeAction((action, state) => {
          console.log("Action Type: ", action.type)
          console.log("Action Payload: ", action.payload)
          console.log("Current State: ", state)
        })
      }],
      state: {
        foo: 1
      },
      mutations: {
        INCREASE_FOO(state) {
          state.foo++;
        },
      },
      actions: {
        increaseFoo({ commit }) {
          commit('INCREASE_FOO');
        }
      }
    });
    
    new Vue({
      el: '#app',
      store,
      methods: {
        onClick() {
          this.$store.dispatch('increaseFoo');
        }
      }
    })
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.2/vue.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vuex/3.0.1/vuex.min.js"></script>
    
    <div id="app">
      Foo state: {{ $store.state.foo }}
      <button @click="onClick">Increase Foo</button>
    </div>