Piniaの使い方|ストアの作成とstate・getters・actions

Piniaの使い方とは

Pinia(ピーニャ)は、Vue の状態管理(いくつもの画面や部品で共有するデータの管理)のためのライブラリーです。Vue 公式ドキュメントは、以前の公式ライブラリーである Vuex はメンテナンスモード(新しい機能は追加されない状態)になっており、新しいアプリケーションには Pinia を使うよう勧めています。

部品どうしでデータを渡す基本は props と emit ですが、離れた画面どうしで同じデータを使いたいとき、何段もの親子を経由して渡すのは大変です。Pinia の「ストア」に置けば、どの部品からでも同じデータを読み書きできます。この記事では、2026年10月時点の Pinia 4.0.3 で動かした例で、ストアの作り方と使い方を説明します。

基本(ストアの3つの要素)

Pinia の公式ガイドでは、ストアは、部品の木構造に縛られない状態と処理を持つもので、state・getters・actions の3つの考え方があり、部品の data・computed・methods に当たると説明しています。

ストアの要素 意味 Composition API での書き方
state 共有するデータ ref()
getters state から計算した値 computed()
actions state を変える処理 ふつうの関数

使う前に、アプリに Pinia を登録します(create-vue で Pinia を選ぶと、src/main.js に最初から書かれています)。

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'

const app = createApp(App)
app.use(createPinia())
app.mount('#app')

サンプルコード(実行結果つき)

src/stores/counter.js(create-vue が作る例そのもの)

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 }
})

ストアを使う画面

<script setup>
import { storeToRefs } from 'pinia'
import { useCounterStore } from '@/stores/counter'

const counter = useCounterStore()
const { count, doubleCount } = storeToRefs(counter)
</script>

<template>
  <p>カウント {{ count }}/2倍 {{ doubleCount }}</p>
  <button type="button" @click="counter.increment()">増やす</button>
</template>

storeToRefs は、ストアから state や getters を取り出しても、変更が画面に反映され続けるようにする関数です。ストアをそのまま分割代入(const { count } = counter)すると、つながりが切れてしまいます。actions(increment)は、counter.increment() のようにストアから直接呼びます。

動作確認(検証環境と結果)

  • Vue 3.5.43、Pinia 4.0.3、Vue Router 5.3.1、Vite 8.3.3、Microsoft Edge、2026年10月。
  • 最初は「カウント 0/2倍 0」、「増やす」を1回押すと「カウント 1/2倍 2」になりました。
  • 別の画面(/about)でも同じストアを読むようにし、ホームで2回増やしてから RouterLink で移動すると、「2(2倍は 4)」と表示されました。
  • ブラウザを再読み込みすると、値は 0 に戻りました。

Piniaの使い方の注意点

  • ストアのデータは、再読み込みで消えます。 メモリの中に置かれているためです。残したいときは、localStorage などに保存する仕組みを別に作ります。
  • 何でもストアに入れない: Pinia の公式ガイドは、ストアには、アプリのあちこちで使うデータ(ナビゲーションに出すユーザー情報や、何ページにもまたがる入力の途中経過など)を置き、1つの画面の中だけの状態(ある要素を見せるかどうか等)は部品の中に置くよう説明しています。
  • defineStore の最初の引数('counter')は、ストアごとに違う名前にします。

Piniaの使い方でよくあるミス

  • app.use(createPinia()) を忘れて、ストアを使うとエラーになる。
  • ストアを分割代入して、表示が変わらなくなる(storeToRefs を使う)。
  • 1つのストアに何でも入れて、どこで何が変わったか分からなくなる。

Piniaの使い方のチェックリスト

  • [ ] main.js で Pinia を登録した
  • [ ] defineStore で、state・getters・actions を書いた
  • [ ] 取り出すときは storeToRefs を使った
  • [ ] ストアに入れるのは、複数の画面で使うデータだけにした

Piniaの使い方のFAQ(よくある質問)

Q. Vuex と Pinia はどちらを学べばいいですか?

A. 新しく作るなら Pinia です。Vue 公式が新しいアプリには Pinia を勧めています。既存のプロジェクトが Vuex を使っているなら、その保守のために Vuex を読む必要があります。

Q. reactive() で作ったオブジェクトを export するのと何が違いますか?

A. 小さなアプリなら、それでも共有できます。Pinia の公式ガイドは、開発者ツールでの追跡や、ファイルを保存したときの再読み込みなしの反映(ホットモジュールリプレースメント)、サーバーサイドレンダリングへの対応などを、Pinia を使う理由として挙げています。

Q. Options API の形でストアを書けますか?

A. 書けます。defineStore に state・getters・actions を持つオブジェクトを渡す書き方もあります。

筆者の見解(Piniaの使い方)

Pinia は便利な分、何でもストアに入れたくなるのが落とし穴だと感じます。私は「2つ以上の画面で使うか」を入れる基準にすることを勧めます。1つの画面の中で完結するデータは、部品の ref で十分で、そのほうが流れを追いやすいからです。まずは create-vue が作る counter の例を読み、そこに自分のデータを1つ足すところから始めると理解が速いと考えます。

Piniaの使い方の関連項目

出典(一次情報)

タイトルとURLをコピーしました