actions 내부에서 state에 접근하지 마라. state를 연산하든 다루든 하는거는 무조건 mutation 안에서 해라.
똑같은 코드, 똑같은 로직을 가진 컴포넌트가 중복되었을 때 사용하는 것? getters
FavoriteValue.vue
<template>
<h3>{{counter}}</h3>
<p>We do more...</p>
</template>
<script>
export default {
computed:{
counter(){
return this.$store.state.counter * 2;
}
}
}
</script>
<style>
</style>
이를 다루기 위해 main.js로 가서 getters를 사용해보자.
main.js
getters: {
finalCounter(state) {
return state.counter * 3;
},
}
TheCounter.vue & FavoriteValue.vue
<template>
<h3>{{counter}}</h3>
</template>
<script>
export default {
computed:{
counter(){
return this.$store.getters.finalCounter;
}
}
}
</script>
<style>
</style>
FavoriteValue.vue에서는 counter값이 100 초과 시 100으로, 0 미만 시 0으로 나타내주고 싶다.
main.js
getters: {
finalCounter(state) {
return state.counter * 3;
},
normalizedCounter(state, getters) {
const finalCounter = getters.finalCounter;
if (finalCounter < 0) {
return 0;
} if (finalCounter > 100) {
return 100;
}
return finalCounter;
}
결과는 다음과 같다.
import { createApp } from 'vue';
import { createStore } from 'vuex';
import App from './App.vue';
const store = createStore({
state() {
return {
counter: 0
};
},
mutations: {
increment(state) {
state.counter += 2;
},
increase(state, payload) {
state.counter = state.counter + payload.value;
}
},
getters: {
finalCounter(state) {
return state.counter * 3;
},
normalizedCounter(_, getters) { //안쓰는 인자는 _ 하면 에러메시지 안뜬대 -> 211005수정) 에러 뜨는데?
const finalCounter = getters.finalCounter;
if (finalCounter < 0) {
return 0;
} if (finalCounter > 100) {
return 100;
}
return finalCounter;
}
}
});
const app = createApp(App);
app.use(store);
app.mount('#app');
이유? → 만약 여러 mutation이 실행될때 모든 mutation은 최신 state를 가지고 수행한다. 만약 다른 mutation이 commit되었을 때 아직 안끝났다면 state값에 있어서 error가 날 수 있기 때문이다.
(mutation에서 setTimeout 써도 되긴 한데 그러면 나중에 문제생길 수 있으니 쓰지 말자)
🗣️ : 그러면 비동기를 수행하려면 어떻게 해야할까???
actions를 사용하면 비동기가 가능하다!
main.js
actions: {
increment(context) {
setTimeout(function () {
context.commit('increment')
}, 2000);
},
increase(context, payload) {
context.commit('increase', payload);
}
},
App.vue
methods: {
addOne() {
this.$store.commit('increase', { value: 10 }); //commit 표현법1
this.$store.dispatch({
type:'increment',
});
},
},
dispatch
를 통해 actions를 사용할 수 있다.main.js 전체코드
import { createApp } from 'vue';
import { createStore } from 'vuex';
import App from './App.vue';
const store = createStore({
state() {
return {
counter: 0
};
},
mutations: {
increment(state) {
state.counter += 2;
},
increase(state, payload) {
state.counter = state.counter + payload.value;
}
},
actions: {
increment(context) {
setTimeout(function () {
context.commit('increment')
}, 2000);
},
increase(context, payload) {
context.commit('increase', payload);
}
},
getters: {
finalCounter(state) {
return state.counter * 3;
},
normalizedCounter(getters) {
const finalCounter = getters.finalCounter;
if (finalCounter < 0) {
return 0;
} if (finalCounter > 100) {
return 100;
}
return finalCounter;
}
}
});
const app = createApp(App);
app.use(store);
app.mount('#app');