티스토리 뷰

Vue&React

Vuex - (2)

U_pic 2022. 4. 26. 02:48

State

Vuex에 저장하는 데이터는 일반적으로 단일 컴포넌트 내에서 선언하는 data의 형식과 동일한 규칙을 따른다.


Vuex의 상태 가져오기

const Counter = {
  template: `<div>{{ count }}</div>`,
  computed: {
    count () {
      return this.$store.state.count
    }
  }
}

mapState의 사용

모든 state를 호출할때마다 써주면 반복적인 코드가 활용될 수 있다.

이러한 코드라인을 절약하기 위해 getter함수를 생성하는 mapState를 활용할 수 있다.

computed: {
  localComputed ()
  // mix this into the outer object with the object spread operator
  ...mapState('peerPaper', ['count']);
}

Getters

기존 state에서 어떤 연산이 추가된 값이 필요할 때 Getters를 사용할 수 있다. 단일 컴포넌트의 computed와 비슷한 역할을 한다. ex) 배열의 길이가 필요할때

store 내부에서 다음과 같이 getters 아래에 로직을 작성하면 이후 여러 컴포넌트에서 동일한 연산을 수행한 값을 받을 수 있다.

getters: {
  // ...
  doneTodosCount (state, getters) {
    return getters.doneTodos.length
  }
}
computed: {
  doneTodosCount () {
    return this.$store.getters.doneTodosCount
  }
}

mapGetters의 사용

store에 저장된 getters를 꺼내어 사용할 수 있다.

import { mapGetters } from 'vuex'export default {
  // ...
  computed: {
    // mix the getters into computed with object spread operator
    ...mapGetters([
      'doneTodosCount',
      'anotherGetter',
      // ...
    ])
  }
}

Mutations

Vuex에서 실제 State로 변경하는 방법은 Mutation을 사용하는 것이다.

Handler 함수는 실제 State를 수정하는 함수이며, 인자로 state를 받는다.

Payload로 Commit

컴포넌트에서 store.commitpayload를 인자로 넘겨 store에서 선언한 mutation을 사용할 수 있다.

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

이때 payload는 다양한 값을 사용할 수 있게 객체 타입으로 넘겨주는 것이 일반적이다.

Mutation은 동기적이어야한다.

Vuex는 모든 상태의 전과 후를 알 수 있어야한다. 이때 Mutation이 비동기적으로 수행되면 상태 변화를 추적할 수 없기 때문에 mutation은 동기적으로 수행되어야 한다.


mapMutations의 사용

mapMutations를 사용하여 store.commit를 직접 사용하지 않더라도 해당 mutation을 활용할 수 있다.

import { mapMutations } from 'vuex'export default {
  // ...
  methods: {
    ...mapMutations([
      'increment', // map `this.increment()` to `this.$store.commit('increment')`// `mapMutations` also supports payloads:
      'incrementBy' // map `this.incrementBy(amount)` to `this.$store.commit('incrementBy', amount)`
    ]),
    ...mapMutations({
      add: 'increment' // map `this.add()` to `this.$store.commit('increment')`
    })
  }
}

Actions

mutation을 실행(commit)하는데 사용된다. Mutations와 Actions의 차이는

  • state를 변화시키기보다, Mutation을 commit한다.

  • 동기적으로 동작해아하는 Actions를 비동기적으로 사용되게끔 해준다.

    → Mutations 자체는 state 변화를 추적할 수 있어야하기 때문에 동기적으로 처리되어야 한다.

    → 그래서 Mutation 자체를 비동기적으로 동작시킴으로서 비동기적으로 처리되게끔 할 수 있다.

// 동기적처리
actions: {
  increment ({ commit }) {
    commit('increment')
  }
}
// 비동기적처리
actions: {
  incrementAsync ({ commit }) {
    setTimeout(() => {
      commit('increment')
    }, 1000)
  }
}

Dispatching Actions

Actions를 사용하기 위해서 store.dispatch를 사용한다.

store.dispatch('incrementAsync', {
  amount: 10
})

// dispatch with an object
store.dispatch({
  type: 'incrementAsync',
  amount: 10
})

MapActions의 사용

import { mapActions } from 'vuex'

export default {
  // ...
  methods: {
    ...mapActions([
      'increment', // map `this.increment()` to `this.$store.dispatch('increment')`

      // `mapActions` also supports payloads:
      'incrementBy' // map `this.incrementBy(amount)` to `this.$store.dispatch('incrementBy', amount)`
    ]),
    ...mapActions({
      add: 'increment' // map `this.add()` to `this.$store.dispatch('increment')`
    })
  }
}

Modules

모듈은 하나의 Store안에서 기능별로 나누어지는 단위.

하나의 Store안에 여러개의 Modules가 있을 수 있다.

각 Module은 각각의 state, mutations, actions, getters, 또는 modules를 가질 수 있다.

const moduleA = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}
const moduleB = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... }
}
const store = createStore({
  modules: {
    a: moduleA,
    b: moduleB
  }
})
store.state.a // -> `moduleA`'s state
store.state.b // -> `moduleB`'s state

Name Space

NameSpace를 활용하여 각 모듈을 이름을 통해 호출할 수 있고, 모듈을 독립적이고 재사용성을 높일 수 있다.

const store = createStore({
  modules: {
    account: {
      namespaced: true,

      // module assets
      state: () => ({ ... }), // module state is already nested and not affected by namespace option
      getters: {
        isAdmin () { ... } // -> getters['account/isAdmin']
      },
      actions: {
        login () { ... } // -> dispatch('account/login')
      },
      mutations: {
        login () { ... } // -> commit('account/login')
      },

      // nested modules
      modules: {
        // inherits the namespace from parent module
        myPage: {
          state: () => ({ ... }),
          getters: {
            profile () { ... } // -> getters['account/profile']
          }
        },

        // further nest the namespace
        posts: {
          namespaced: true,

          state: () => ({ ... }),
          getters: {
            popular () { ... } // -> getters['account/posts/popular']
          }
        }
      }
    }
  }
})

'Vue&React' 카테고리의 다른 글

[React] Modal with Portal  (0) 2022.05.10
Context API  (0) 2022.04.27
Vuex - (1)  (0) 2022.04.26
[Vue.js] style scoped  (0) 2022.04.10
React에서 .env (환경변수) 파일 사용하기  (0) 2022.03.21
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/01   »
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 31
글 보관함