3

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.

2
  • Are you asking for a recommendation for a library/product, or how to do it yourself? Commented Nov 2, 2017 at 2:18
  • Sorry, how to do it myself. I have seen a few libs out there, most wrap all existing actions in an additional function to handle the mutation. At this point that seems the only option, but I wanted to check if anyone else has done something along these lines first. Redux, for example, allows this using it's middleware, although I guess Vuex does not. Commented Nov 2, 2017 at 4:06

2 Answers 2

7

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>

Sign up to request clarification or add additional context in comments.

2 Comments

perfect. I didn't know this was in vuex, relatively recent addition. Thanks!
what if I need to run something before and after every action? like setting loader status in active or inactive state
1

Since 3.1.0, subscribeAction can also specify whether the subscribe handler should be called before or after an action dispatch (the default behavior is before):

store.subscribeAction({
  before: (action, state) => {
    console.log(`before action ${action.type}`)
  },
  after: (action, state) => {
    console.log(`after action ${action.type}`)
  }
})

documentation: https://vuex.vuejs.org/api/#subscribeaction

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.