티스토리 뷰

Vue.JS

[vuex] Mutations

버미노트 2019. 7. 10. 23:23

Vuex의 store에서 실제로 state를 변경할 수 있는 유일한 방법은 변이(Mutation) 하는 것입니다. Vuex의 Mutation은 이벤트와 유사합니다. 각 Mutation에서는 문자열 타입과 핸들러가 있습니다. 핸들러 함수는 실제 state를 수정하는 곳이고, 첫번째 전달인자로 state를 받습니다.

const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    increment (state) {
      // 상태 변이
      state.count++
    }
  }
})

Mutation의 핸들러를 직접 호출 할 수는 없습니다. mutation 옵션은 이벤트 등록과 비슷합니다. 타입이 increment인 Mutation가 발생하면 핸들러를 호출합니다.

store.commit('increment')

Mutation 핸들러를 호출하려면 위의 코드처럼 store.commit을 사용해야 합니다.

1. Commit with payload

Matation을 커밋한다는 말은 Mutation 핸들러를 실행 시킨다는 말로 사용할 것입니다. Commit with payload란 Mutation 핸들러에 payload를 전달하는 의미입니다. store.commit에 payload라고 하는 추가 전달인자를 사용할 수 있습니다.

// ...
mutations: {
  increment (state, n) {
    state.count += n
  }
}
store.commit('increment', 10)

대부분의 경우 payload는 여러 필드를 포함 할 수 있는 객체를 사용하는 것이 좋습니다.

// ...
mutations: {
  increment (state, payload) {
    state.count += payload.amount
  }
}
store.commit('increment', {
  amount: 10
})

객체 스타일 payload 커밋

Mutation를 커밋하는 또 다른 방법은 type 속성을 가진 객체를 사용하는 것입니다.

store.commit({
  type: 'increment',
  amount: 10
})

객체 스타일 커밋을 사용할 때 사용 된 객체는 Mutation 핸들러에 payload로 전달 되기 때문에 핸들러는 동일하게 사용 하면 됩니다.

mutations: {
  increment (state, payload) {
    state.count += payload.amount
  }
}

2. 변이(Mutation)는 Vue의 반응성 규칙을 따릅니다.

Vuex의 state를 관찰 하고 있는 컴포넌트가 Vuex의 state 변경을 감지하고 자동으로 화면을 업데이트 해줍니다. 자동으로 화면을 업데이트 하기 위해서는 2가지를 지켜야 합니다.

  1. 사용하는 모든 필드를 store에 초기화 하는 것이 좋습니다.
  2. 객체에 새 속성을 추가 할 때, Vue.set(obj, 'newProp', 123)을 사용하거나, 객체를 새로운 객체로 교체해야 합니다.
state.obj = { ...state.obj, newProp: 123 }

위의 코드와 같이 객체 전개 연산자를 사용하여 새로운 객체로 교체 할 수 있습니다.

3. Mutation Type 상수

Flux 구현에서 mutation type 상수를 사용하는 것이 일반적입니다. 상수들을 하나의 파일에 저장하면 여러 작업자들이 전체 어플리케이션이 어떤 Mutation이 있는지 한 눈에 파악 할 수 있습니다.

// mutation-types.js
export const SOME_MUTATION = 'SOME_MUTATION'
// store.js
import Vuex from 'vuex'
import { SOME_MUTATION } from './mutation-types'

const store = new Vuex.Store({
  state: { ... },
  mutations: {
    // ES2015에서 계산 된 프로퍼티 이름 기능을 사용하여
    // 상수를 함수 이름으로 사용할 수 있습니다
    [SOME_MUTATION] (state) {
      // 변이 상태
    }
  }
})

Mutation Type 상수를 따로 관리할지 결정하는 것은 온전히 개발자의 선택에 달려있습니다.

4. Mutation의 핸들러 함수는 반드시 동기적이어야 합니다.

Mutation의 핸들러 함수는 반드시 동기적으로 작성되어야 합니다.

mutations: {
  someMutation (state) {
    api.callAsyncMethod(() => {
      state.count++
    })
  }
}

예를 들면, 위의 코드와 같이 비동기로 동작하는 코드가 있습니다. 디버깅 하기 위해 devtool를 이용하여 mutation 로그를 보고 있다고 가정합시다. devtool은 state의 이전과 이후를 스냅샷으로 캡처해야 합니다. 그러나 Mutation이 비동기적으로 동작한다면, 핸들러 함수가 종료되었지만 state가 변경되지 않는 상태가 발생합니다. devtool 입장에서는 핸들러 함수 속에 있는 콜백함수가 실제로 호출되었는지 알 수 있는 방법이 없습니다. 이러한 이유로 Mutation의 핸들러 함수는 반드시 동기적이어야 합니다.

5. mapMutations

this.$store.commit('xxx')를 사용하여 컴포넌트에서 Mutation의 핸들러 함수를 호출할 수 있습니다. store.commit와 동일한 역할을 하는 헬퍼는 mapMutations 입니다.

import { mapMutations } from 'vuex'

export default {
  // ...
  methods: {
    ...mapMutations([
      'increment' // this.increment()를 this.$store.commit('increment')에 매핑합니다.
    ]),
    ...mapMutations({
      add: 'increment' // this.add()를 this.$store.commit('increment')에 매핑합니다.
    })
  }
}

위의 코드와 같이 mapMutations를 사용할 수 있습니다.

참고

'Vue.JS' 카테고리의 다른 글

[vuex] Modules  (0) 2019.07.16
[vuex] Actions  (0) 2019.07.11
[vuex] Mutations  (0) 2019.07.10
[vuex] Getters  (0) 2019.07.02
[vuex] State  (0) 2019.06.28
[vuex] Vuex 시작하기  (0) 2019.06.26
댓글
댓글쓰기 폼