# Actions Actions are functions that dispatch mutations. Actions can be asynchronous and a single action can dispatch multiple mutations. An action expresses the intention for something to happen, and abstracts the details away from the component calling it. When a component wants to do something, it just calls an action - there's no need to worry about a callback or a return value, because actions result in state changes, and state changes will trigger the component's DOM to update - the component is completely decoupled from how that action is actually performed. > Vuex actions are in fact "action creators" in vanilla flux definitions, but I find that term more confusing than useful. ### Simple Actions It is common that an action simply triggers a single mutation. Vuex provides a shorthand for defining such actions: ``` js const vuex = new Vuex({ state: { count: 1 }, mutations: { INCREMENT (state, x) { state += x } }, actions: { // shorthand // just provide the mutation name. increment: 'INCREMENT' } }) ``` Now when we call the action: ``` js vuex.actions.increment(1) ``` It simply calls the following for us: ``` js vuex.dispatch('INCREMENT', 1) ``` Note any arguments passed to the action is also passed along to the mutation handler. ### Thunk Actions How about actions that involve logic depending on current state, or that need async operations? We can define these actions as **thunks** - essentially functions that return another function: ``` js const vuex = new Vuex({ state: { count: 1 }, mutations: { INCREMENT (state, x) { state += x } }, actions: { incrementIfOdd: function (x) { return function (dispatch, state) { if ((state.count + 1) % 2 === 0) { dispatch('INCREMENT', x) } } } } }) ``` Here, the outer function receives the arguments passed when calling the action. Then, it returns a function that gets 2 arguments: first is the `dispatch` function, and the second being the `state`. We are using ES5 syntax here to make things easier to understand. With ES2015 arrow functions we can "prettify" the above to the following: ``` js // ... actions: { incrementIfOdd: x => (dispatch, state) => { if ((state.count + 1) % 2 === 0) { dispatch('INCREMENT', x) } } } ``` The string shorthand is essentially syntax sugar for the following: ``` js actions: { increment: 'INCREMENT' } // ... equivalent to: actions: { increment: (...args) => dispatch => dispatch('INCREMENT', ...args) } ``` Why don't we just define the actions as simple functions that directly access `vuex.state` and `vuex.dispatch`? The reason is that couples the action functions to the specific vuex instance. By using the thunk syntax, our actions only depend on function arguments and nothing else - this important characteristic makes them easy to test and hot-reloadable! ### Async Actions We can use the same thunk syntax for defining async actions: ``` js // ... actions: { incrementAsync: x => dispatch => { setTimeout(() => { dispatch('INCREMENT', x) }, 1000) } } ``` A more practical example is when checking out a shopping cart - we may need to trigger multiple mutations: one that signifies the checkout has started, one for success, and one for failure: ``` js // ... actions: { checkout: products => (dispatch, state) => { // save the current in cart items const savedCartItems = [...state.cart.added] // send out checkout request, and optimistically // clear the cart dispatch(types.CHECKOUT_REQUEST) // the shop API accepts a success callback and a failure callback shop.buyProducts( products, // handle success () => dispatch(types.CHECKOUT_SUCCESS), // handle failure () => dispatch(types.CHECKOUT_FAILURE, savedCartItems) ) } } ``` Again, all the component needs to do to perform the entire checkout is just calling `vuex.actions.checkout(products)`.