Vue Vuex 액션

YEZI🎐·2022년 12월 13일
0

Vue

목록 보기
43/45

액션

액션은 mutations와 유사하다. 다른 점은,

  • 상태를 mutations시키는 대신 액션으로 mutations에 대한 commit을 한다.
  • 작업에는 임의의 비동기 작업이 포함될 수 있다.
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.statecontext.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는 트리거 된 액션 핸들러에 의해 반환된
    Promise를 처리 할 수 있고 Promise를 반환함
    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')
       })
     }
    }
  • JavaScript 기능 async/await 사용
    // getData() 및 getOtherData()가 Promise를 반환한다고 가정
    actions: {
     async actionA ({ commit }) {
       commit('gotData', await getData())
     },
     async actionB ({ dispatch, commit }) {
       await dispatch('actionA') // actionA가 끝나기를 기다림
       commit('gotOtherData', await getOtherData())
     }
    }
profile
까먹지마도토도토잠보🐘

0개의 댓글