34

I have a list of filters I want to apply to a json object.

My mutations look like this:

const mutations = {
    setStars(state, payload) {
        state.stars = payload;
        this.dispatch('filter');
    },

    setReviews(state, payload) {
        state.reviews = payload;
        this.dispatch('filter');
    }
};

Because of how filters work I need to re-apply them all again since I can't simply keep downfiltering a list because this gets me into trouble when a user de-selects a filter option.

So when a mutation is being made to a stars filter or reviews filter(user is filtering) I need to call a function that runs all my filters.

What is my easiest option here? Can I add some kind of helper function or possible set up an action which calls mutations that actually filter my results?

7
  • 1
    When you need to return a filtered data, there is no need to mutate your storage. Keep your data intact and create a getter which returns filtered data, either 2 getters (1 for each case) or a single getter which accepts an argument (filter condition). Related reading: vuex.vuejs.org/en/getters.html Commented Jun 1, 2017 at 14:25
  • @wostex I would agree with you if it were just one filter but I need to apply multiple filters at once for a single value. So I can not just use 1 or 2 getters separately. They need to work together. Commented Jun 1, 2017 at 14:26
  • A getter can call another getter. Commented Jun 1, 2017 at 14:28
  • @wostex true but I would need any getter to call every other getter that is a filter and do this for all getters. It would get messy real fast. Perhaps I don't really see what you mean but thanks for the tip anyways! Commented Jun 1, 2017 at 14:29
  • Here's what I mean basically: jsfiddle.net/wostex/u2yoLgLb Commented Jun 1, 2017 at 14:49

2 Answers 2

50

Mutations can't dispatch further actions, but actions can dispatch other actions. So one option is to have an action commit the mutation then trigger the filter action.

Another option, if possible, would be to have all filters be getters that just naturally react to data changes like a computed property would.

Example of actions calling other actions:

// store.js
export default {
  mutations: {
    setReviews(state, payload) {
      state.reviews = payload
    }
  }

  actions: {
    filter() {
      // ...
    }

    setReviews({ dispatch, commit }, payload) {
      commit('setReviews', payload)
      dispatch('filter');
    }
  }
}


// Component.vue
import { mapActions } from 'vuex';

export default {
  methods: {
    ...mapActions(['setReviews']),
    foo() {
      this.setReviews(...)
    }
  }
}
Sign up to request clarification or add additional context in comments.

4 Comments

So with every mutation I do, I need to call a dispatch straight after it from my Vue components? Since I am not able to call an action from a mutation inside my Vuex store?
@Stephan-v i would actually have the components dispatch a setReviews action instead of a mutation. The action can both the commit the setReviews mutation and trigger the filter action.
Makes sense. How do I properly call another action from an action inside my Vuex store though?
@Stephan-v actions receive context as their first parameter, which contains a dispatch function you can use. I updated my post with a quick, untested example
7

You can actually dispatch actions from a mutation by using this. For example:

const actions = {
  myAction({ dispatch, commit }, { param }) {
  // Do stuff in my action
  }
}

const mutations = {
  myMutation(state, value) {

    state.myvalue = value;
    this.dispatch('myModule/myAction', { param: 'doSomething' });
  },
}

3 Comments

I strongly discourage anyone from doing this. It is very much an anti-pattern. Mutations are very clearly intended to be synchronous / blocking code, where as actions are not. This is in essence undermining the strict role mutations have by permitting them to do more than they should do (that is, take some property of state and modify it with the input its received in some way).
@Lev I agree that this is indeed an anti-pattern but the part about Actins being async only isn't true. Yes async code should be placed in Actions but Actions can as well contain synchronous code.
Mutations are synchronous and should never call actions as this will be anti-pattern. Instead actions may call other actions using dispatch. This way async calls of any actions will not cause issue. But calling actions from mutations will cause state update issues and hang up of rendering

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.