VueX Actions

VueX Actions: can be used interchangeably with mutations however, actions be used to commit mutations asynchronously whereas mutations can only be synchronous.

Vuex Actions accepts context object as argument for each handler functions and this context contains commit, state, getters, and dispatch as it store instance.

In order to call handler functions inside Actions properties from vue component, we use this.$store.dispatch('deductPrice'). 

When it dispatches from vue component, actions handler function will call mutations handler function with payload injected.

Example:
simple.js


import Vue from 'vue';
import Vuex, { mapGetters, mapMutations } from 'vuex';
Vue.use(Vuex)


const store = new Vuex.Store({
state: {
products:[
{id:1,name:'pizza', price:10},
{id:2, name:'fan', price: 20},
{id:3, name:'headset', price:30 },
{id:4,name: 'phone', price: 1004}
]
},
mutations: {
deductPrice( state, payload ) {
return state.products.map(item => item.price -= payload.price)
}
},
getters:{
getBigPrice (state) {
return state.products.filter(item => item.price >= 10)
},
getCountItem ( state, getters ) {
return getters.getBigPrice.length
}
},
actions:{
deductPrice(context){
context.commit('deductPrice',{price: 1})
}
}
})

const Counter = {
template: `<div> Total {{ itemCount }}
<li v-for="product in products"> Id:{{ product.id }},
name:{{ product.name }}, Price:{{ product.price }} </li><br/>
<button @click="deductPrice">Deduct</button>
</div>`,
computed:{
...mapGetters(
{ products: 'getBigPrice',
itemCount: 'getCountItem'}
)
},
methods:{
deductPrice(){
this.$store.dispatch('deductPrice')
}
}
}
export {store, Counter }

App.vue
<template>
<div id="app">
<Counter />
</div>
</template>

<script>
import {store, Counter } from './state/simple'

export default {
name: 'app',
store,
components: {
Counter
},
data () {
return {
placeHolder: 'Focus on me'
}
},

}
</script>

Final result

By using ES2015, you can destruct commit from context object 
actions:{
deductPrice({commit}){
commit('deductPrice',{price: 1})
}
}

Actions can be asynchronous as below. We use setTimeout for testing.
actions:{
deductPrice({commit}){
setTimeout(()=>{
commit('deductPrice',{price: 1})
},1000)
}
}

In vue component, this.$store.dispatch can carry out payload or object.

Payload:
methods:{
deductPrice(){
this.$store.dispatch('deductPrice', { price: 1})
}
}

Object:
methods:{
deductPrice(){
this.$store.dispatch({type:'deductPrice', price: 1})
}
}

Composing Actions

Actions can be composed asynchronously by using Promise or async and await

Example: simple.js
import Vue from 'vue';
import Vuex, { mapGetters, mapMutations } from 'vuex';
Vue.use(Vuex)


const store = new Vuex.Store({
state: {
products:[
{id:1,name:'pizza', price:10},
{id:2, name:'fan', price: 20},
{id:3, name:'headset', price:30 },
{id:4,name: 'phone', price: 1004}
]
},
mutations: {
deductPrice( state ) {
return state.products.map(item => item.price -= 1)
},
multPrice( state, payload ) {
return state.products.map(item => item.price *= payload.price)
}
},
getters:{
getBigPrice (state) {
return state.products.filter(item => item.price >= 10)
},
getCountItem ( state, getters ) {
return getters.getBigPrice.length
}
},
actions:{
deductPrice({commit}) {
return new Promise((resolve, reject) => {
setTimeout(() => {
commit('deductPrice')
resolve()
},1000)
})
},
multPrice( { commit, dispatch }, payload ) {
return dispatch('deductPrice').then(() => {
commit('multPrice', payload)
})
}
}
})

const Counter = {
template: `<div> Total {{ itemCount }}
<li v-for="product in products"> Id:{{ product.id }},
name:{{ product.name }}, Price:{{ product.price }} </li><br/>
<button @click="deductPrice">Deduct</button>
<button @click="multPrice">Multiply</button>
</div>`,
computed:{
...mapGetters(
{ products: 'getBigPrice',
itemCount: 'getCountItem'}
)
},
methods:{
deductPrice(){
this.$store.dispatch({type:'deductPrice'})
},
multPrice() {
this.$store.dispatch({ type:'multPrice', price:2 })
}
}
}
export {store, Counter }

when you click on multiply button, you may see multPrice waits for deductPrice to finish first.

please see result for detail




Comments

Popular posts from this blog

Vuex mapMutations

VueX Modules