Posts (Vue.js) Vuex 상태관리자 시작하기 (3) - actions, mapActions 헬퍼
Post
Cancel

(Vue.js) Vuex 상태관리자 시작하기 (3) - actions, mapActions 헬퍼

Vuex 에서 Actions 는 상태 커밋을 지시하는 역할을 합니다.

속성설명사용
GettersVuex 상태의 계산된 속성 조회store.state
MutationsVuex 상태 변이store.commit(..)
ActionsVuex 상태 변이 지시store.dispatch(..)

Actions 를 사용하지 않더라도 직접 Mutation commit 을 통해 상태 변이를 일으킬 수 있습니다.
그럼 우리는 왜, 언제 Actions 를 사용해야 할까요?

우리는 어플리케이션을 개발할때 서버로부터 데이터를 받아와 화면에 표출하거나 커스텀하는 기능을 구현 합니다. 이 경우 당연히 비동기 코드가 들어가게 되죠

setTimeout, Promise, Api 호출 (ajax, axios …) 등 모두 비동기 코드 입니다

Actions 는 바로 이런 비동기 동작을 수행하기 위해 사용합니다.
Vuex 의 핵심 컨셉을 보면 변이는 무조건 동기적이어야 한다 라고 나와 있습니다. 이 말은 즉 Mutations 핸들러 함수 내에서 api 호출과 같은 비동기 동작을 사용해선 안된다는 의미이죠

우리는 Vue 에서 공식적으로 제공하는 dev-tools 를 통해 Vuex 상태 변이의 스냅샷을 확인할 수 있습니다.
그런데 Mutations 핸들러 안에서 언제 상태가 commit 될지 모르는 비동기적 코드가 들어가 된다면 ?
디버깅이 힘들어지게 되겠죠. 그렇기 때문에 변이는 항상 동기적 이어야 합니다.

이런 비동기 동작에 대한 갈증을 해소하기 위해 Actions 를 사용할 수 있습니다
컴포넌트에서 Actions 를 dispatch(발행) 하고, Actions 안에서 api 호출과 같은 비동기 작업 수행 및 commit 합니다.

Actions dispatch (발행)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
new Vuex.store({
    state: {
      currentProduct: null
    },
    mutations: {
      setCurrentProduct(state, product) {
        state.currentProduct = product // 3. 상태 업데이트 
      }
    },
    actions: {
      async fetchProduct(context, productNo) { // 1. 상품조회 api 호출
        const product = await axios.get('/api/product', { params: { productNo } }) 
        context.commit('setCurrentProduct', product) // 2. 상품 설정 commit 
      }
    }
  }
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<template>
  <div>
    <p>상품명: {{ currentProduct.name }}</p>
    <p>가격: {{ currentProduct.price }}</p>
    <p>할인율: {{ currentProduct.discount }}%</p>
    <button @click="getCurrentProduct()">상품조회</button>
  </div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
  data: function () {
    return {
      productNo: 1000,
    }
  },
  computed: {
    ...mapGetters(['currentProduct'])
  }, 
  methods: {
    getCurrentProduct() {
      if (confirm(`${this.productNo}번 상품을 조회하겠습니까?`)) {
        //🍀 Dispatch(발행) 은 아래와 같은 2가지 타입으로 가능합니다 :)
        this.$store.dispath('fetchProduct', {productNo: this.productNo}) // 방법1) 콤마로 구분하여 전달
        // this.$store.dispath({ type: 'fetchProduct', productNo: this.productNo}) 방법2) 객체로 전달
      }
    }
  }
}
</script>

mapActions 헬퍼

Actions 도 마찬가지로 Vuex 에서 헬퍼를 제공하기 때문에 컴포넌트 methods 에 매핑하여 좀 더 간단하게 사용할 수 있습니다 😊

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<template>
  <div>
    <p>상품명: {{ currentProduct.name }}</p>
    <p>가격: {{ currentProduct.price }}</p>
    <p>할인율: {{ currentProduct.discount }}%</p>
    <button @click="getCurrentProduct()">상품조회</button>
  </div>
</template>
<script>
import { mapGetters, mapActions } from 'vuex'
export default {
  data: function () {
    return {
      productNo: 1000,
    }
  },
  computed: {
    ...mapGetters(['currentProduct'])
  }, 
  methods: {
    ...mapActions(['fetchProduct']), 
    getCurrentProduct() {
      if (confirm(`${this.productNo}번 상품을 조회하겠습니까?`)) {
        this.fetchProduct(productNo)
      }
    }
  }
}
</script>
This post is licensed under CC BY 4.0 by the author.

(Vue.js) Vuex 상태관리자 시작하기 (2) - mutations, mapMutations 헬퍼

(Vue.js) Vuex 저장소 모듈로 분리하기 (modules)

Comments powered by Disqus.