はじめに
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 pinia
Pinia を 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
が主流になっていくため、ぜひ習得しましょう!
コメント