state에 있는 데이터를 store에서 변경하기 위해 mutations를 사용했다.
컴포넌트 내부에서 상태를 직접 변경해서는 안된다.
(전에 발행한 mutations에 관한 글↓)
# state를 직접 읽어오는것의 문제 - 코드의 중복
직접 상태를 읽어오는 것도 이상적이지 않을 수 있다.
왜 이상적이지 않을까?
이 앱에서는 TheCounter.vue 컴포넌트에서 counter를 출력한다.
또 다른 컴포넌트인 FavoriteValue.vue를 추가해보자.
TheCounter.vue와 동일하되, 'We do more...'라는 글자를 추가해보자.
이 컴포넌트를 사용하기 위해 App.vue에서 FavoriteValue 컴포넌트를 불러오자.
counter가 두개가 있고, 둘다 업데이트가 잘 된다.
이제 이 counter에 2를 곱한 값을 출력해보자.
FavoriteValue.vue에 업데이트하고, TheCounter.vue에서도 업데이트하자.
computed: {
counter() {
return this.$store.state.counter * 2;
},
},
자, 여기서 문제가 발견되었다.
→ 바로, 코드의 중복
규모가 더 큰 애플리케이션에서는 충분히 발생할 수 있는 상황이다.
다른 컴포넌트에 같은 종류의 데이터가 여러개 있는 경우,
데이터의 형식을 바꾸거나 계산값을 다르게 바꿔야 한다면 다른 모든 컴포넌트에서 해당 코드를 수정해야한다.
그렇기 때문에 상태와 직접 통신하지 않는 이유!
# 해결책 - Getters
이 때 게터(Getters)라는 개념을 사용할 수 있다.
이 개념은 computed 프로퍼티와 같이, 저장소에 직접 정의되어 우리가 원하는 컴포넌트 내부에서 사용할 수 있다.
## Getters 추가 방법
게터를 Vuex 저장소에 추가해보자.
mutations 옆에 (위치 중요x) getters를 추가해보자.
게터는 객체를 받는다. 이제 이 객체의 모든 게터는 메서드이다.
computed 프로퍼티가 컴포넌트의 computed옵션에 있는 메서드인것처럼,
여기서 finalCounter라는 게터를 가질 수 있다.
finalCounter 게터 메서드는 Vuex에 있는 모든 게터 메서드처럼 두 개의 인수를 받는다.
→ 첫 번째 인수인 state에서는 현재 상태를 가져와야하고, 두 번째 인수는 getters이다.
여기서 계산하려는 값이 다른 게터의 결과에 따라 달라지는 경우 게터에 다른 게터를 넣는 것이 유용할 수 있다.
지금은 무시하고, state 인수만 작업하자.
값을 반환하자.
그 값은 state에서 관리되는 counter로, 2를 곱한 값이다.
getters: {
finalCounter(state){
return state.counter * 2;
}
}
## 컴포넌트 내에서 Getters 사용방법
이제 원하는 어떤 컴포넌트에서도 이 게터를 사용할 수 있다.
TheCounter.vue 컴포넌트 내에서 computed 프로퍼티에서 this.$store에 접근하여 state가 아닌, $store.getters에 접근한다.
그리고 게터 이름을 입력한다. 이 경우, finalCounter이다.
호출을 하거나 실행하는 것이 아니고, 그저 가리킬 뿐이다.
가리키면 Vuex가 getter메서드를 실행할 것이고, 현재 state를 게터에 전달한다.
<template>
<h3>{{ counter }}</h3>
<p>We do more...</p>
</template>
<script>
export default {
computed: {
counter() {
return this.$store.getters.finalCounter;
},
},
};
</script>
이제 counter의 값을 3으로 곱하고 싶다면, 두 곳(TheCounter.vue, FavoriteValue.vue)이 아닌 한 곳(main.js의 getters객체)에서 코드를 수정하면 된다.
이렇게 저장하면 잘 작동하는 것을 확인할 수 있다.
## 여러 개의 getters
여러 개의 게터를 가질 수 있고, 게터는 서로에게 의존할 수 있다.
예를 들어 finalCounter 게터 외에 또다른 게터인 normalizedCounter를 추가해보자.
finalCounter값을 사용하여 이 값이 0보다 크고 100보다 작게 만들고 싶다.
이 범위를 벗어나면 0이나 100을 출력하게 하고싶다.
이를 구축할 하나의 방법으로는 counter * 3을 다시 계산하여 finalCounter라는 상수에 저장하고,
만약 finalCounter가 0보다 작으면 0을 출력하고, 100보다 크면 100을 출력한다.
이 두 가지 경우가 아닐때만 finalCounter를 출력한다.
getters: {
finalCounter(state) {
return state.counter * 3;
},
normalizedCounter(state) {
const finalCounter = state.counter * 3;
if (finalCounter < 0) {
return 0;
}
if (finalCounter > 100) {
return 100;
}
return finalCounter;
},
},
참고로 게터에 두 줄 이상의 코드를 넣을 수 있다(게터의 또 다른 장점이기도 하다.).
이제 normalizedCounter가 있고, 이걸 FavoriteValue.vue 컴포넌트에 사용해보자.
<!--FavoriteValue.vue-->
<template>
<h3>{{ counter }}</h3>
<p>We do more...</p>
</template>
<script>
export default {
computed: {
counter() {
return this.$store.getters.normalizedCounter;
},
},
};
</script>
이제 100을 초과하면 아래 counter는 100을 출력한다.
이렇게도 잘 작동하지만, 좋은 방법은 아니다.
왜냐하면, 다른 게터에서 계산한 것을 또 계산하고 있기 때문(const finalCounter = state.counter * 3;)
## getters의 두 번째 인수 - getters
이를 피하고자 getters라는 두 번째 인수를 추가한다.
이것으로 게터를 참조하여 finalCounter를 가져온다. getters.finalCounter를 호출하면 된다.
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;
},
},
만약 finalCounter게터 안에 더 많은 코드가 있었다고 상상해보자.
getters 인수가 있다면 다른 게터에 있는 모든 코드를 복제할 필요가 없다.
따라서 getters인수로 finalCounter를 사용할 수 있다.
위 경우, 첫번째 인수인 state인수가 필요하지 않다.
따라서 여기서는 state인수는 밑줄(_)로 대체하자.
** 이 프로젝트 설정에서 사용하는 관행으로 두 번째 인수를 얻기 위해 getters인수는 사용하지만, state인수로는 작업하지 않는다는 뜻.
이렇게 해놓지 않으면 이 프로젝트의 설정은 사용하지 않는 인수에 대해 문제를 제기하기 때문에 관행을 사용해야한다.
** 출처: 모든 내용은 Udemy Vue-완벽가이드 강의를 기반으로 작성하였습니다.
'Vue.js' 카테고리의 다른 글
[Udemy Vue 완벽가이드 Section15] 219. 액션 "컨텍스트" 이해하기 (0) | 2023.10.25 |
---|---|
[Udemy Vue 완벽가이드 Section15] 218. 액션(Actions)으로 비동기 코드 실행하기 (0) | 2023.10.25 |
[Udemy Vue 완벽가이드 Section15] 216. payload를 사용하여 변형(Mutation)에 데이터 전달 (0) | 2023.10.24 |
[Udemy Vue 완벽가이드 Section15] 215. 변형(Mutation) 소개 - 데이터를 변경하는 더 나은 방법 (0) | 2023.10.24 |
[Udemy Vue 완벽가이드 Section15] 214. 상태에 컴포넌트 연결하기 (0) | 2023.10.24 |