Vue/Vuex

Vuex 핵심 컨셉(4) - 액션(actions)

고코모옹 2021. 7. 1. 18:08

- 액션(actions)

  • 변이(mutation)와 유사
  • 변이와 차이점
    • 상태를 변이 시키는 대신 액션으로 변이에 대한 커밋을 함
    • 작업에는 임의의 비동기 작업이 포함될 수 있음

  • 액션 Handler는 Store 인스턴스의 동일한 메소드/프로퍼티 정보를 가지고 있는 컨텍스트(context) 객체를 받는다.
    • context.commit: 변이를 커밋
    • context.state: 상태에 접근
    • context.getters: getters에 접근
// store/index.js
const store = createStore({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment (context) {
      context.commit('increment')
    }
  }
})
actions: {
  // 코드를 단순화하기 위해 ES6 구조 분해 할당 사용
  increment ({ commit }) {
    commit('increment')
  }
}

 

- 디스패치 액션

  • 액션은 store.dispatch 메소드로 시작
store.dispatch('increment')
  • 비동기 작업을 수행하기 위해 사용(mutation은 동기적이어야 함)
actions: {
  incrementAsync ({ commit }) {
    setTimeout(() => {
      commit('increment')
    }, 1000)
  }
}
  • mutation과 동일하게 payload객체 type을 지원
// 페이로드와 함께 디스패치
store.dispatch('incrementAsync', {
  amount: 10
})

// 객체와 함께 디스패치
store.dispatch({
  type: 'incrementAsync',
  amount: 10
})
  • 액션의 실용적인 예는 비동기 API 호출여러 개의 변이를 커밋하는 장비구니 결제
    • 비동기 작업의 흐름을 수행하고 커밋하여 작업의 사이드이펙트(상태 변이)를 기록
actions: {
  checkout ({ commit, state }, products) {
    // 장바구니에 현재있는 항목을 저장하십시오.
    const savedCartItems = [...state.cart.added]

    // 결제 요청을 보낸 후 장바구니를 비웁니다.
    commit(types.CHECKOUT_REQUEST)

    // 상점 API는 성공 콜백 및 실패 콜백을 받습니다.
    shop.buyProducts(
      products,
      // 요청 성공 핸들러
      () => commit(types.CHECKOUT_SUCCESS),
      // 요청 실패 핸들러
      () => commit(types.CHECKOUT_FAILURE, savedCartItems)
    )
  }
}

 

- 액션 구성하기

  • 액션은 비동기 처리가 가능하다. 그러면 액션이 언제 완료되는지 어떻게 알 수 있을까? 복잡한 비동기 흐름을 처기하기 위해 어떻게 여러 작업을 함께 구성해야 할까?
  • 가장 먼저 알아야 할 점은 store.dispatch가 트리거 된 액션 Handler에 의해 반환된 Promise를 처리할 수 있으며 Promise를 반환한다는 것
// store.js
actions: {
  actionA ({ commit }) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        commit('someMutation')
        resolve()
      }, 1000)
    })
  }
}

// Vue component에서 호출
store.dispatch('actionA').then(() => {
  // ...
})
  • 액션 안에 또 다른 액션 사용 가능
actions: {
  // ...
  actionB ({ dispatch, commit }) {
    return dispatch('actionA').then(() => {
      commit('someOtherMutation')
    })
  }
}
  • 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())
  }
}

 

[ 참고자료 ]

https://next.vuex.vuejs.org/guide/actions.html#composing-actions

 

Actions | Vuex

Actions Actions are similar to mutations, the differences being that: Instead of mutating the state, actions commit mutations.Actions can contain arbitrary asynchronous operations. Let's register a simple action: const store = createStore({ state: { count:

next.vuex.vuejs.org