Vue 3 + Typescript + Piniaで状態管理
前書き
Vue3をインストールしたときにPiniaのサンプルとして入っているcounter.tsが、関数を使ったコードに変わっていた為、記事にまとめようと思いました。
nodeのバージョンは v16.17.0 で行っております
本題
インストール
今回の開発は以下の方法でインストールしています。
npm init vue@latest
✔ Project name: … vue-pinia
✔ Add TypeScript? … Yes
✔ Add JSX Support? … No
✔ Add Vue Router for Single Page Application development? … Yes
✔ Add Pinia for state management? … Yes
✔ Add Vitest for Unit Testing? … No
✔ Add an End-to-End Testing Solution? › No
✔ Add ESLint for code quality? … No
counter.tsについて
今回の前書きにある、counter.tsについて確認します。
/src/stores/counter.tsを開いてみましょう。
import { ref, computed } from 'vue'
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
const doubleCount = computed(() => count.value * 2)
function increment() {
count.value++
}
return { count, doubleCount, increment }
})
2022/12現在では上記になっており、以前までは下記のコードとなっていました。
調べても下記のコードの記事が多いかと思います。
import { defineStore } from 'pinia'
interface State {
count: number
}
export const useCounterStore = defineStore("counter", {
state: (): State => ({ count: 0 }),
getters: {
doubleCount: (state) => {
return state.count * 2
}
},
actions: {
increment() {
this.count++
}
}
})
見比べてみる
基本的な(id: ストア名, state: データ本体定義,getters: データ加工処理定義,actions: データ変更処理定義)の考え方は変わっていません。
それでは見比べていきましょう。
state
state: (): State => ({ count: 0 })
const count = ref(0)
refを使ったコードに変わっています。ちなみに、refを使って型指定を行う場合は、ジェネリクス引数を与えてあげることで指定できます。
const count = ref<number>(0)
getters
getters: {
doubleCount: (state) => {
return state.count * 2
}
}
const doubleCount = computed(() => count.value * 2)
stateをrefで管理することで、stateへのアクセスが変わりました。
またgettersは、stateの値をもとに算出した結果を取得するので、同じ動きをするcomputedを使っています。
actions
actions: {
increment() {
this.count++
}
}
function increment() {
count.value++
}
actionsもgettersと同じでrefを使ったstateへのアクセスになっています。
その他
idのコードは変わっていませんので、第一引数に書いていただければ大丈夫です。
他に変わったところといえば、最後のreturnでしょうか。
defineStoreをexportしていればそのまま使えていましたが、関数での書き方ではstate, getters, actions全てをreturnをしなければなりません。
後書き
見てくださった方はどちらのコードの方がよかったでしょうか。
個人的には関数でのコードの方が感覚的に書けて、書きやすいと感じました。
また、OpenWeatherMapを使って、今回の本題の書き方でGitHubに上げていますので、宜しければ参考にして下さい。
Discussion