[Vue3실강] 11강 Pinia

youngseo·2022년 6월 8일
0
post-thumbnail

Pinia

Vue의 공식 상태 관리 라이브러리가 Pinia 로 변경되었습니다 . Pinia는 Vuex 5 RFC 에 설명된 Vuex 5와 거의 동일하거나 향상된 API를 가지고 있습니다. Pinia를 다른 이름의 Vuex 5로 생각할 수 있습니다.

Vuex vs Pinia

⭐Pinia는 TypeScript를 지원합니다.

  • vuex에서 module을 지원하긴 하지만 각각 흩어져있는 moudule파일들에 대한 state의 타입을 추론하는 것이 어려웠습니다.
  • 그런데 Pinia는 defineStore라는 함수를 이용하여 각각의 파일마다 별도의 store를 정의하여 module의 기능을 대신합니다.
  • vuex의 this.$store와는 달리 pinia는 defineStore가 반환하는 hook을 이용하여 store에 아주 쉽게 접근할 수 있습니다.
  • 그렇기에, 반환 된 hook은 내부 구성 요소에 대한 타입을 포함하고 있으며, 타입 추론에 대한 그 어떤 작업도 추가로 필요하지 않습니다.
  • 따라서 타입스크립트를 도입하고 컴포지션 API를 적용하는 경우 그 장점이 확연하게 들어날 수 있습니다.

1. core concepts

vuex에서는core concepts로 state,Getters, Mutations, Actions, Modules5가지 개념을 도입했습니다.

Pinia에서는 state,Getters,action세가지 개념을 사용합니다. (모듈화는 필수적으로 적용되게 됩니다.)

mutations이 없어 권한이 없어 사용하기 편한 대신에 그로인해 발생하는 에러에 대한 책임을 져야합니다.

2. pinia 적용

2-1 pinia설치

$ npm i pinia

2-2 store>index.js

🎨차이점

vuex를 사용할 때는 store폴더를 만들어 그 안에 index.js라는 기본 파일을 만들었습니다.

만약, message라는 이름으로 모듈화를 하는 경우 store폴더 안에는 모듈이 하나더라도 message.js와 index.js파일로 총 2개의 파일이 존재해야했습니다.

하지만, pinia는 index.js 없이 모듈화된 파일만 있으면 됩니다.

🎨차이점

또한 vuex에서는 모듈화된 파일의 상단에 namedspaced:true가 필요했습니다. 하지만 피니아는 모듈이 기본 옵션이기에 따로 필요하지 않습니다.

store>message.js

import {defineStore} from 'pinia'

//이름을 가지는 내보내기
//첫번쨰 인수로 사용하고자 하는 모듈의 이름을 넣어줘야합니다
export const useMessageStore = defineStore('message',{
  //화살표함수로 하면 좋습니다.
  state: () => ({
    message: 'Hello world!'
  }),
  getters: {
    reversedMessage(state) {
      return state.message.split('').reverse().join('')
    }
  },
  actions: {
    reverseMessage() {
      //this로 접근
      this.message = this.message.split('').reverse().join('')
    }
  },
})

🔑이름을 가지는 내보내기를 할 때 보통 이름 앞에 use를 붙여 사용합니다.

🎨공통점 : state

vuex에서는 mutations에서 state에 접근하기 위해 state라는 매개변수를 사용했습니다. 마찬가지로 pinia에서도 getters에서 state에 접근하기 위해 state를 매개변수로 받습니다.

🎨차이점 : context

vuex에서는 actions의 매개변수로 context(={state,getters,commit,dsipatch})를 사용했습니다.

하지만 pinia에서는 this를 통해 보다 편하게 접근을 할 수 있습니다.

2-2 store의 state를 가져오기

🎨vuex에서는

vuex에서는 아래와 같이 state의 정보를 가져올 수 있었습니다.

1) 첫번째 방법
computed: {
  message() {
    return this.$store.state.message.message
  }
}

만약 매핑을 하는 경우 아래와 같이 사용할 수 있었습니다.

2) 두번쨰 방법
import {mapState} from 'vuex'

computed: {
  ...mapState('message', [
      message
    ]),
}

🎨pinia에서는

하지만 pinia에서는 첫번째 방법은 사용을 할 수 없습니다

about.vue

import {mapState} from 'pinia' //1
import {useMessageStore} from '~/store/message' //2

export default {
  computed: {
    ...mapState(useMessageStore, [ //3
      'message'
    ])
  }
}
  1. mapState을 사용하는 경우 마찬가지로 pinia에서 mapState를 가지고 와 등록하면 됩니다.

  2. 단 피니아는 모든 것이 모듈이기 때문에 그 모듈을 직접가져와야합니다.

  3. 그리고 vuex에서는 모듈이름이 들어갔던 자리에 모듈을 통채로 집어넣습니다

2-3 피니아 등록하기

main.js

import { createApp } from 'vue'
import { createPinia } from 'pinia'import router from './routes'
import '~/routes/guards'
import App from './App.vue'

createApp(App)
  .use(createPinia())✅호출합니다
  .use(router)
  .mount('#app')

2-4 연결확인하기

About.vue

<template>
  <h1>About!</h1>
  <RouterLink to="/about/name">
    Name~
  </RouterLink>
  <RouterView />
  <div>{{ message }}</div>
</template>

2-5 store의 getters 가져오기

🎨vuex에서는

import {mapState, mapGetters} from 'vuex'

와 같이 mapGetters를 가져왔습니다

🎨pinia에서는

getter도 mapState에서 가지고 옵니다.

<template>
  <h1>About!</h1>
  <RouterLink to="/about/name">
    Name~
  </RouterLink>
  <RouterView />
  <div>{{ message }}</div>
  <div>{{ reversedMessage }}</div>
</template>
<script>
import {mapState} from 'pinia'
import {useMessageStore} from '~/store/message'

export default {
  computed: {
    ...mapState(useMessageStore, [
      'message',
      'reversedMessage'
    ])
  }
}
</script>

2-5 store의 actions 가져오기

🎨pinia에서는

mapActions에서 actions를 가져올 수 있습니다.

<template>
  <h1>About!</h1>
  <RouterLink to="/about/name">
    Name~
  </RouterLink>
  <RouterView />
  <div>{{ message }}</div>
  <div>{{ reversedMessage }}</div>
  <button @click="reverseMessage">
    Reverse!!
  </button>
</template>
<script>
import {mapState, mapActions✅} from 'pinia'
import {useMessageStore} from '~/store/message'

export default {
  computed: {
    ...mapState(useMessageStore, [
      'message',
      'reversedMessage'
    ])
  },
  methods: {...mapActions(useMessageStore,[
      'reverseMessage'
    ])
  }
}
</script>

2-6 mapStores

mapState, mapActions대신 사용할 수 있는 개념이 새로 나왔습니다.

등록하는 방법

<script>
import {mapStores} from 'pinia'
import {useMessageStore} from '~/store/message'

export default {
  computed: {
    ...mapStores([useMessageStore]) 
  },
}
</script>

위와 같이 등록을 해줍니다.

사용하는 방법

<template>
  <h1>About!</h1>
  <RouterLink to="/about/name">
    Name~
  </RouterLink>
  <RouterView />
  <div>{{✅ messageStore.message }}</div>
  <div>{{✅ messageStore.reversedMessage }}</div>
  <button @click="✅messageStore.reverseMessage">
    Reverse!!
  </button>
</template>

useMessageStore에서 use를 뺀 객체데이터를 붙여줍니다.

messageStore라는 이름 범위 안에서 사용을 하기 때문에 관리가 조금 더 용이합니다.

<button @click="messageStore.message='HEROPY?!@'">
  HEROPY
</button>

위와 같이 state의 데이터를 수정해버릴 수도 있습니다.


참고

1개의 댓글

comment-user-thumbnail
2022년 8월 18일

안녕하세요

올려주신 글 잘 보았습니다

궁금한 점이 있어서 댓글을 남깁니다

main.js 자체에서 pinia를 사용하여 store를 수정 할 수 있을까요?

ex) vue로 만들어진 홈페이지나 app을 접속 하면 main에서 아이디값을 localstorage를 확인 후 있으면 로그인 처리한다

이런식으로 하고 싶습니다 가능 할까요?

답글 달기