본문 바로가기
IT/Pinia

Pinia - Getter ( Option Store )

by 2T1 2023. 1. 2.
이 글은 Vue 3의 공식 Store | Pinia 를 보고 정리한 글입니다.
더 자세한 내용을 원하시면 공식 문서를 참고하세요.

 

 

Store 상태에 대한 계산된 값과 정확히 동일합니다.defineStore()내에서 getters 속성으로 정의할 수 있습니다.

화살표 함수의 사용을 권장하기 위해, 첫 번째 인자로 state를 받습니다:

export const useCounterStore = defineStore('counter',{
  state: () => ({
    count : 0,
  }),
  getters: {
    doubleCount: (state) => state.count * 2,
  },
})

대부분, Getter는 오직 State에만 의존하지만, 다른 getter를 사용해야 할 수도 있습니다.

이 때문에 일반 함수를 정의할 때, this를 통해 전체 store 인스턴스에 접근할 수 있지만, 반환 유형을 정의해야합니다 (TypeScript를 사용할때).

 

이것은 TypeScript의 알려진 제한 사항 때문이며, 화살표 함수로 정의된 게터나 this를 사용하지 않는 게터에 영향을 미치지 않습니다.

export const useCounterStore = defineStore('counter', {
  state: () => ({
    count: 0,
  }),
  getters: {
    // 자동으로 반환 유형을 숫자로 유추함.
    doubleCount(state) {
      return state.count * 2
    },
    
    // 반환 유형은 **반드시** 명시적으로 설정되어야 함.
    doublePlusOne(): number {
      // 전체 스토어에 대한 자동 완성 및 타이핑 ✨
      return this.doubleCount + 1
    },
  },
})

 

 

그런 다음 스토어 인스턴스에서 직접 게터에 접근할 수 있습니다:

<template>
  <p>Double count is {{ store.doubleCount }}</p>
</template>

<script>
export default {
  setup() {
    const store = useCounterStore()

    return { store }
  },
}
</script>

 

다른 getter에 접근

여러 getter를 결합하여 사용할 수 있습니다. this를 통해 다른 getter에 접근합니다.

export const useCounterStore = defineStore('counter', {
  state: () => ({
    count: 0,
  }),
  getters: {
    // `this`를 사용하지 않기 때문에 유형이 자동으로 유추됨.
    doubleCount: (state) => state.count * 2,
    // 여기에 유형을 직접 추가해야 함(JS에서 JSDoc 사용).
    // 이것을 사용하여 게터를 문서화할 수도 있음.
    /**
     * count에 2를 곱한 값에 1을 더해 반환.
     *
     * @returns {number}
     */
    doubleCountPlusOne() {
      // 자동완성 ✨
      return this.doubleCount + 1
    },
  },
})

TypeScript를 사용하지 않는 경우에도 JSDoc를 사용하여 유형에 대해 IDE에 힌트를 줄 수 있습니다


 

getter에 인자 전달

getter는 내부적으로 계산된 속성일 뿐이라 parameter를 전달할 수 없습니다. 그러나 getter에서 함수를 반환하여 모든 인자를 받을 수 있습니다 :

export const useStore = defineStore('main', {
  getters: {
    getUserById: (state) => {
      return (userId) => state.users.find((user) => user.id === userId)
    },
  },
})

 

 

 

<script>
export default {
  setup() {
    const store = useStore()

    return { getUserById: store.getUserById }
  },
}
</script>

<template>
  <p>유저 2: {{ getUserById(2) }}</p>
</template>

 

 

 

이 작업을 수행할 때 getter는 더이상 캐시되지 않고, 단순히 호출하는 함수입니다. 그러나 getter 자체 내부에 일부 결과를 캐시할 수 있습니다. 이는 흔하지는 않지만 우수한 성능을 가지고 있습니다 :

export const useStore = defineStore('main'.{
  getters: {
    getActiveUserById(state){
      const activeUsers = state.users.filter((user)=> user.active)
      return (userId) => activeUsers.find((user)=>user.id === userId)
    },
  },
})

 

다른 스토어 getter에 접근

import { useOtherStore } from './other-store'

export const useStore = defineStore('main', {
  state: () => ({
    // ...
  }),
  getters: {
    otherGetter(state) {
      const otherStore = useOtherStore()
      return state.localData + otherStore.data
    },
  },
})

 

setup() 에서 사용

store의 모든 getter를 state 속성처럼 직접 접근할 수 있습니다.

export default {
  setup(){
    const store = useCounterStore()
    
    store.count = 3
    store.doubleCount
  }
}

 

 

Option API 에서 사용

// 예제 파일 경로:
// ./src/stores/count.js

import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', {
  state: () => ({
    count: 0
  }),
  getters: {
    doubleCount(state) {
      return state.count * 2
    }
  }
})

 

 

setup() hook을 사용하면 Option API에서 피니아를 더 쉽게 사용할 수 있습니다.

추가 map Helper 함수가 필요하지 않습니다.

import { useCounterStore } from '../stores/counter'

export default {
  setup() {
    const counterStore = useCounterStore()

    return { counterStore }
  },
  computed: {
    quadrupleCounter() {
      return this.counterStore.doubleCount * 2
    },
  },
}

 

 

setup() 없이는 이전 섹션인 상태에서 사용한 것과 동일한 mapState() 함수를 사용하여 게터에 매핑할 수 있습니다:

import { mapState } from 'pinia'
import { useCounterStore } from '../stores/counter'

export default {
  computed: {
    // 컴포넌트 내부에서 `this.doubleCount`로 접근할 수 있게 함.
    // `store.doubleCount`로 읽는 것과 동일.
    ...mapState(useCounterStore, ['doubleCount']),
    // 위와 같지만 `this.myOwnName`으로 등록.
    ...mapState(useCounterStore, {
      myOwnName: 'doubleCount',
      // 스토어에 접근하는 함수를 작성할 수도 있음.
      double: (store) => store.doubleCount,
    }),
  },
}

'IT > Pinia' 카테고리의 다른 글

Vue3 ) script setup  (0) 2023.03.28
Pinia - Action ( Option Store )  (0) 2023.01.02
Pinia - State ( Option Store )  (0) 2023.01.02
Pinia  (0) 2022.12.30