Piniaを用いたグローバルステート管理

こんにちは。株式会社レスキューナウのmap protoチームでフロントエンドを担当している濱崎です。
現在フロントでは Vue3 + vite + Typescript での開発を行っておりグローバルステート管理としてPiniaを採用しています。

Piniaを使うにあたっての導入手順や使い方、Vuexとの違いをここでは紹介していければと思います。

ライブラリをインストールする

yarn add pinia@next
# or with npm
npm install pinia@next

プロジェクトへのインストール

# main.ts

import { createApp } from "vue";
import App from "./App.vue";
import { createPinia } from "pinia";

const app = createApp(App);
app.use(createPinia());

app.mount("#app");

storeの作成

ここはチームによって変わってくるかとは思いますが、所属チームではsrc配下にstoreフォルダを作って管理しています。

defineStoreの第一引数としてユニークなキー、第二引数としてstate, getters, actionsの3つのプロパティを定義していきます。

# src/store/hoge.ts

import { defineStore } from 'pinia'

export const gameStore = defineStore({
  id: 'hoge',
  state: () => ({
    name: 'レスキュー太郎'
  }),
  getters: {
    getName() {
      return this.name
    }
     ...
  },
  actions: {
    setName() {
      this.name = 'レスキュー花子'
    }
     ...
  }
})

ここでVuexと大きく違う点としてPiniaにはmutationsがありません。
actionsの中で直接stateの値を更新していきます。

また、thisでstateにアクセスすることが可能となっています。

この点は意見の分かれるところだとは思いますが個人的にはVuexに比べ簡素な記述でstate更新できるようになっており扱いやすいという印象を持ちました。

コンポーネントからのアクセス

<template>
  <div>{{store.name}}</div>
  <div>{{store.getName}}</div>
  <button @click="store.setName">setName</button>
</template>
<script setup>
  import { hogeStore } from '../../store/hoge'
  const store = hogeStore()
</script>

アクセスも非常に簡単で定義したstoreをコンポーネント側から呼び出すだけで各プロパティへアクセスすることができます。

またstoreToRefsを用いた分割代入も可能となっています。

<template>
  <div>{{name}}</div>
  <div>{{getName}}</div>
  <button @click="setName">setName</button>
</template>
<script setup>
  import { hogeStore } from '../../store/hoge'
  import {storeToRefs} from 'pinia'

  const store = hogeStore()

  const {name, getName, setName} = storeToRefs(store)
</script>

この際にtoRefsだとreactivityが失われるので注意が必要です。

まとめ

今回はPiniaの導入から使用方法を簡単にまとめさせていただきましたが記載させていただいたようにPiniaは非常に簡単にグローバルステート管理を行えます。
Vuexとの違いとしてmutationsが廃止されたことにより冗長なcodeを書く必要がなくなった点や今回は触れていませんがPiniaはTypeScript のフルサポートもありVuexで問題(Vuex4.xはTypeScriptのサポートを受けています)であった型安全なステート管理が行える点も大きいかと思います。

また将来的にPiniaはVuex5に統合されるのではないかとの話も出ており今の段階でPiniaを使用することでVuex5への導入が容易になる期待が持てそうですね。

最後まで読んでいただき、ありがとうございました。

最後に
現在、レスキューナウでは、災害情報の提供、災害情報を活用した安否確認サービスなどのWebサービスの開発エンジニアを募集しています!
社員・フリーランスに関わらず、参画後に安心してご活躍できることを目指し、応募された方の特性・ご希望にマッチしたチームをご紹介します。
ちょっと話を聞いてみたい、ぜひ応募したい、など、当社にご興味を持っていただけましたら、お気軽にエントリーください!!