By looking at the documentation mutations and actions are defined as such:
Actions
Actions are similar to mutations, the differences being that:
Instead of mutating the state, actions commit mutations.
Actions can contain arbitrary asynchronous operations.
Mutations
The only way to actually change state in a Vuex store is by committing a mutation. Vuex mutations are very similar to events: each mutation has a string type and a handler. The handler function is where we perform actual state modifications, and it will receive the state as the first argument:
(...) One important rule to remember is that mutation handler functions must be synchronous
It is imperative that state modifications are done using mutations, else the updates wont be dispatched properly through the Vue app and the components won't update accordingly. But you are not forced to use actions to commit mutations. You could think of actions as a composition of mutations that allow you to handle complex changes to your state and asynchronous methods. So, if your action is simple enough use a mutation, else use an action. Although, be aware that as mutations are synchronous, they may freeze your front-end until the requested action is over, if the action is a heavy one (nice explication of Akryum, vuejs core member here).
In a similar manner the getters are a way of "formatting" data retrieved from the store, as stated in the docs:
Sometimes we may need to compute derived state based on store state, for example filtering through a list of items and counting them.
Meaning that if you just need a simple key from the state you don't need to create a getter, you can simply retrieve the info you need from the state.
Taking a look to your example:
testAction: ({commit, getters, state}, testData) => {
if(state.foo === 'bar'){ // is this bad practice? ==> Good to go !
// ...do a thing
}
if(getters.getFoo === 'bar'){ // should I always read the state with a getter like this instead? ==> Good to go ! but it depends on the way you can retrieve data from the state (like if you need to know the number of items within a list)
// ...do a thing
}
commit('setFoo', 'testData'); // do I always need to set the state via commit like this ==> **YES** !
state.foo = 'foobar' // or is it fine to just do this? ==> never do this
}
Also for an easier integration of VueX in your components, the api exposes a set of functions to access the store properties and use them as computed properties or methods: mapActions
, mapMutations
, mapGetters
and mapState