はじめに
Vue.js でアプリを作ると、コンポーネント同士でデータを共有することが増えてきます。
小規模なら props や emit で対応できますが、大規模になると管理が複雑になります。
そこで役立つのが Pinia(ピニャ) という 状態管理ライブラリ です!
本記事では、Pinia の基本概念・使い方・実践例 まで、初心者向けにわかりやすく解説します!
Pinia とは?
状態管理とは?
Vue.js では、コンポーネントごとにデータ(data())を管理できますが、複数のコンポーネントでデータを共有 しようとすると、props や emit でのやり取りが増えて 管理が大変 になります。
Pinia を使うメリット
- 状態(データ)を一元管理 → どのコンポーネントからでもアクセス可能
- Vuex よりシンプルで使いやすい
- TypeScript との相性が良い
- 非同期処理も簡単に管理できる
Pinia のストアの概念と基本的な使い方
Pinia の 3 つの主要機能
| 機能 | 役割 |
|---|---|
| state | アプリ全体のデータ(状態)を管理 |
| actions | state を変更する関数(同期・非同期) |
| getters | state を加工して取得 |
Pinia ストアの構成
import { defineStore } from "pinia";
export const useCounterStore = defineStore("counter", {
state: () => ({ count: 0 }),
actions: {
increment() { this.count++ },
async asyncIncrement() { setTimeout(() => { this.increment() }, 1000) }
},
getters: {
doubleCount: state => state.count * 2
}
});
Pinia をプロジェクトに導入する方法
Vue CLI や Vite を使っている場合、以下のコマンドで Pinia をインストールできます。
npm install piniaPinia を 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");
これでアプリ全体で store が使えるようになります!
state を使ったデータ管理
state はアプリ全体のデータを保存する場所です。
カウントの state を定義
import { defineStore } from "pinia";
export const useCounterStore = defineStore("counter", {
state: () => ({
count: 0
})
});
- 第一引数のcounterはストアを一意に識別するための名前です。
コンポーネントで state を使用
<template>
<p>カウント: {{ store.count }}</p>
</template>
<script setup>
import { useCounterStore } from "@/stores/counter";
const store = useCounterStore();
</script>
store.count にアクセスすることで、アプリのどこからでもデータを取得可能!
actions で state を変更
actions は state を変更するための関数です。
カウントを増やす actions
export const useCounterStore = defineStore("counter", {
state: () => ({
count: 0
}),
actions: {
increment() {
this.count++;
}
}
});
コンポーネントで actions を呼び出し
<template>
<button @click="store.increment">増やす</button>
</template>
<script setup>
import { useCounterStore } from "@/stores/counter";
const store = useCounterStore();
</script>
ボタンをクリックすると store.increment() で state.count が増える!
actions で非同期処理を管理
actions を使うと API 取得や setTimeout を使った非同期処理 を実装できます。
actions で非同期処理を追加
export const useCounterStore = defineStore("counter", {
state: () => ({
count: 0
}),
actions: {
async asyncIncrement() {
setTimeout(() => {
this.increment();
}, 1000);
}
}
});
コンポーネントで actions を呼び出し
<template>
<button @click="store.asyncIncrement">1秒後に増やす</button>
</template>
<script setup>
import { useCounterStore } from "@/stores/counter";
const store = useCounterStore();
</script>
ボタンをクリックすると 1 秒後に state.count が増える!
getters で state を加工して取得
getters は state のデータを 計算して取得 できます。
state.count を 2 倍にする getters
export const useCounterStore = defineStore("counter", {
state: () => ({
count: 0
}),
getters: {
doubleCount: state => state.count * 2
}
});
コンポーネントで getters を使用
<template>
<p>2倍のカウント: {{ store.doubleCount }}</p>
</template>
<script setup>
import { useCounterStore } from "@/stores/counter";
const store = useCounterStore();
</script>
リアルタイムで計算された値を取得可能!
Pinia の実践例(カウンターアプリ)
Pinia を使ってシンプルなカウンターアプリを作成!
stores/counter.js
import { defineStore } from "pinia";
export const useCounterStore = defineStore("counter", {
state: () => ({
count: 0
}),
actions: {
increment() { this.count++; },
async asyncIncrement() { setTimeout(() => { this.increment(); }, 1000); }
},
getters: {
doubleCount: state => state.count * 2
}
});
App.vue
<template>
<p>カウント: {{ store.count }}</p>
<p>2倍のカウント: {{ store.doubleCount }}</p>
<button @click="store.increment">増やす</button>
<button @click="store.asyncIncrement">1秒後に増やす</button>
</template>
<script setup>
import { useCounterStore } from "@/stores/counter";
const store = useCounterStore();
</script>
Pinia を使えば、どのコンポーネントからでも count を管理できる!
Vuex と Pinia の違い
| 比較項目 | Vuex | Pinia |
|---|---|---|
| 記述量 | 多い | 少ない |
| 非同期処理 | actions で commit を呼ぶ | actions 内で直接 state を変更できる |
| 型安全性 | なし | TypeScript に適している |
まとめ
piniaの使い方(defineStoreの基本構文)は以下の通りです。
import { defineStore } from "pinia";
export const useCounterStore = defineStore(
"counter", // ① ストアID
{
state: () => ({ count: 0 }), // ② ストアの状態(state)
actions: {
increment() {
this.count++;
}
}, // ③ アクション(メソッド)
getters: {
doubleCount: state => state.count * 2
} // ④ ゲッター(計算プロパティ)
}
);
| 引数 | 説明 | 必須 |
|---|---|---|
id | ストアを識別するための名前 | ✅ |
state | アプリの状態(データ) | ✅ |
actions | データを変更する関数(同期/非同期) | ❌ |
getters | state を加工して取得する関数 | ❌ |
今後の Vue 3 開発では Pinia が主流になっていくため、ぜひ習得しましょう!


コメント