Episode 7 of 8

Actions

Handle asynchronous operations with actions — dispatch actions that perform async work and then commit mutations to update state.

Actions

Mutations must be synchronous. But real apps need asynchronous operations — API calls, timers, file reads. Actions handle the async logic and then commit mutations when the work is done.

The Flow

Component ──dispatch──→ Action ──(async work)──→ commit ──→ Mutation ──→ State

Defining Actions

// store/store.js
export const store = new Vuex.Store({
    state: {
        products: [
            { id: 1, name: 'Banana Skin', price: 20 },
            { id: 2, name: 'Shiny Star', price: 40 },
            { id: 3, name: 'Green Shells', price: 60 },
            { id: 4, name: 'Red Shells', price: 80 },
            { id: 5, name: 'Mushroom', price: 15 }
        ]
    },
    mutations: {
        reducePrice(state, amount) {
            state.products.forEach(product => {
                product.price -= amount;
            });
        }
    },
    actions: {
        reducePrice(context, amount) {
            // Simulate an async operation (e.g., API call)
            setTimeout(() => {
                context.commit('reducePrice', amount);
            }, 2000);
        }
    }
});

Actions receive a context object that has the same methods and properties as the store instance. You call context.commit() to trigger a mutation.

Dispatching Actions from Components

<template>
    <div>
        <button @click="reducePrice">Reduce Prices (2 sec delay)</button>
    </div>
</template>

<script>
export default {
    methods: {
        reducePrice() {
            this.$store.dispatch('reducePrice', 4);
        }
    }
};
</script>

Use this.$store.dispatch('actionName', payload) instead of commit. The action runs, performs async work, and then commits the mutation when ready.

Destructuring Context

actions: {
    reducePrice({ commit }, amount) {
        setTimeout(() => {
            commit('reducePrice', amount);
        }, 2000);
    }
}

Since you usually only need commit, you can destructure it from the context for cleaner code.

Actions with API Calls

actions: {
    async fetchProducts({ commit }) {
        const response = await fetch('/api/products');
        const data = await response.json();
        commit('setProducts', data);
    }
}

mutations: {
    setProducts(state, products) {
        state.products = products;
    }
}

commit vs dispatch

MethodCallsUse When
this.$store.commit()A mutation (synchronous)No async work needed — change state immediately
this.$store.dispatch()An action (can be async)Async work (API calls, timers) before changing state

Key Takeaways

  • Actions handle async logic and then commit mutations to change state
  • Dispatch actions with this.$store.dispatch('actionName', payload)
  • Actions receive a context object — destructure { commit } for cleaner code
  • Use commit for synchronous state changes, dispatch for async workflows