액션은 mutations와 유사하다. 다른 점은,
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
context.commit('increment')
}
}
})
액션 핸들러는 저장소 인스턴스의 같은 메소드들∙프로퍼티 세트를 드러내는 context 객체를 받는다.
그래서 context.commit
을 호출하여 mutations을 commit하거나
context.state
와 context.getters
를 통해 상태와 getters에 접근 할 수 도 있다.
실제로 (특히 commit를 여러 번 호출해야하는 경우) 코드를 단순화하기 위해
ES2015 전달인자 분해(destructuring)를 사용한다.
actions: {
increment ({ commit }) { // 이 부분
commit('increment') // 이 부분
}
}
액션은 store.dispatch
메소드로 시작된다.
store.dispatch('increment')
상태 mutations은 devtool은 상태의 이전∙이후 스냅샷을 기록할 수 없어 동기적 이어야 했지만,
액션은 비동기 작업을 수행하여 commit 후 작업의 사이드이펙트(상태 변이)을 기록할 수 있기 때문에 액션 내에서 비동기 작업을 수행할 수 있다.
actions: {
incrementAsync ({ commit }) {
setTimeout(() => {
commit('increment')
}, 1000)
}
}
또한, 액션은 mutations과 마찬가지로 payload 타입과 객체 스타일의 디스패치를 지원한다.
// payload와 함께 디스패치
store.dispatch('incrementAsync', {
amount: 10
})
// 객체와 함께 디스패치
store.dispatch({
type: 'incrementAsync',
amount: 10
})
아래와 같이 checkout 이라는 액션을 만들고,
(이 경우 shop API를 사용하여 콜백을 받는) 비동기 작업을 수행 할 수 있다.
actions: {
checkout ({ commit, state }, products) {
// 장바구니에 현재있는 항목 저장
const savedCartItems = [...state.cart.added]
// 결제 요청후 장바구니 비우기
commit(types.CHECKOUT_REQUEST)
// shop API로 성공 or 실패 콜백을 받음
shop.buyProducts(
products,
// 요청 성공 핸들러
() => commit(types.CHECKOUT_SUCCESS),
// 요청 실패 핸들러
() => commit(types.CHECKOUT_FAILURE, savedCartItems)
)
}
}
this.$store.dispatch('xxx')
를 사용하여 컴포넌트에서 액션을 디스패치하거나 컴포넌트 메소드를 store.dispatch
호출에 매핑하는 mapActions 헬퍼를 사용할 수 있다.
import { mapActions } from 'vuex'
export default {
// ...
methods: {
...mapActions([
'increment' // this.increment()을 this.$store.dispatch('increment')에 매핑
// mapActions는 payload 지원
'incrementBy' // this.incrementBy(amount)를 this.$store.dispatch('incrementBy', amount)에 매핑
]),
...mapActions({
add: 'increment' // this.add()을 this.$store.dispatch('increment')에 매핑
})
}
}
store.dispatch
는 트리거 된 액션 핸들러에 의해 반환된actions: {
actionA ({ commit }) {
return new Promise((resolve, reject) => {
setTimeout(() => {
commit('someMutation')
resolve()
}, 1000)
})
}
}
store.dispatch('actionA').then(() => {
// ...
})
그리고 안에 또 다른 액션 사용 가능actions: {
// ...
actionB ({ dispatch, commit }) {
return dispatch('actionA').then(() => {
commit('someOtherMutation')
})
}
}
// getData() 및 getOtherData()가 Promise를 반환한다고 가정
actions: {
async actionA ({ commit }) {
commit('gotData', await getData())
},
async actionB ({ dispatch, commit }) {
await dispatch('actionA') // actionA가 끝나기를 기다림
commit('gotOtherData', await getOtherData())
}
}