이 둘의 차이는 무엇일까?
mutation이 없다. 뷰엑스에서 mutation과 action을 같이 사용하는 코드를 보자. 굉장히 이해하기 어려워보인다. mutation을 action 안에서 사용하기 위해 action이 commit을 인자로 받고 그 commit을 사용해서 Mutation을 사용하면서 state를 mutation 안에서 변경하고….
피니아는 mutation이 없다. 그냥 state를 변경하는 로직을 action 안에서 해 주면 된다.
state, getter, mutation, action을 사용하기 위해서는 따로 context 객체 안의 함수를 사용해야 한다. mutation은 commit, action은 dispatch… 피니아는 이렇게 context 객체를 사용할 필요 없이, 마치 자바스크립트 메서드와 비슷하게 바로 접근해서 사용할 수 있다.
예를 들어 counter에 관련된 store를 만든다고 생각해보자. stores/counter.js에 defineStore로 스토어를 만들어 export할 수 있다.
스토어를 선언하는 방법은 크게 setup stores와 option stores로 나눌 수 있다. 그냥 형식만 다르고, 마치 vue3에서 composition api와 options api 크게 두 가지로 컴포넌트를 구성하는 것과 같다.
vuex store과 비교해보면
// option store
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => ({
counter: 0
}),
getters: {
doubleCount: (state) => state.counter * 2
// doubleCount: function () { return this.counter * 2 }
// 이렇게도 가능하다.
},
actions: {
increment() {
this.counter++
console.log(this.doubleCount) // getter도 this로 바로 접근 가능.
}
}
return { count, doubleCount, increment }
})
// setup store
import { ref, computed } from 'vue'
export const useCounterStore = defineStore('counter', () => {
const count = ref(0) // state
const doubleCount = computed(() => { // getter
return count.value * 2
})
function increment() { // action
count.value++
}
return { count, doubleCount, increment }
})
// vuex store
import { createStore } from 'vuex'
export default createStore({
state: {
counter: 0
},
getters: {
doubleCount: (state) => state.counter * 2
// doubleCount: function () { return this.state.counter * 2 }
// 이렇게는 안 된다.
},
mutations: { // pinia는 mutation이 없다.
increment_mutation (state) {
state.counter++
}
// increment_mutation () {
// this.state.counter++
// }
// 가능하다.
},
actions: {
increment_action ({ commit }) { // context 객체를 받아와 사용할 수 있다.
commit('increment_mutation')
}
// increment_action ({ commit }) {
// this.commit('increment_mutation')
// }
// 가능하다.
}
})
각 store는 고유의 id가 필요한데, 이는 vue devtool에 마운트시켜서 사용하기 위함이다.