現代のフロントエンド開発において、状態管理はアプリケーションのパフォーマンスと保守性に直結する重要な要素です。Vue 3の導入に伴い、公式推奨の状態管理ライブラリであるPiniaが注目を集めています。本記事では、Piniaの導入から実装までを解説し、コードサンプルを通じて実践的な使い方を紹介します。
Piniaとは?
Piniaは、Vuexの代替として設計されたVue用状態管理ライブラリです。特徴的な点は以下の通り:
- シンプルなAPI:defineStore関数を用いて簡単にストアを定義可能
- Composition APIとの親和性:Vue 3のComposition APIと連携して、リアクティブな状態管理を実現
- 開発体験の向上:デバッグツールによるホットリロードやタイムトラベル機能をサポート
導入と初期設定
npmまたはyarnでインストールします:
# npmの場合
npm install pinia
# yarnの場合
yarn add pinia
Vue 3プロジェクトに接続するには以下のように設定します:
// main.js
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
const app = createApp(App)
const pinia = createPinia()
app.use(pinia)
app.mount('#app')
ストアの作成と使用
Piniaの核心となるAPIはdefineStoreです。以下にカウンターアプリを例にしたストアの実装を示します。
ストアの定義
// stores/counter.js
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => ({
currentCount: 0
}),
getters: {
doubleValue(state) {
return state.currentCount * 2
}
},
actions: {
increment() {
this.currentCount++
},
decrement() {
this.currentCount--
}
}
})
コンポーネントでの使用
<!-- components/Counter.vue -->
<template>
<div>
<h2>カウンターアプリ</h2>
<p>現在値: {{ counter.currentCount }}</p>
<p>倍値: {{ counter.doubleValue }}</p>
<button @click="counter.increment">増やす</button>
<button @click="counter.decrement">減らす</button>
</div>
</template>
<script setup>
import { useCounterStore } from '../stores/counter'
const counter = useCounterStore()
</script>
<style scoped>
button {
margin-right: 8px;
}
</style>
高度な使い方
複数ストアの統合
大規模アプリでは、以下のように関連するストアを分離して管理できます:
// stores/user.js
import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', {
state: () => ({
username: '',
isLoggedIn: false
}),
actions: {
login(name) {
this.username = name
this.isLoggedIn = true
},
logout() {
this.username = ''
this.isLoggedIn = false
}
}
})
コンポーネント内で複数ストアを使用する例:
<!-- components/Dashboard.vue -->
<template>
<div>
<h2>ダッシュボード</h2>
<div v-if="user.isLoggedIn">
<p>ようこそ、{{ user.username }}さん!</p>
<button @click="user.logout">ログアウト</button>
</div>
<div v-else>
<button @click="user.login('田中')">ログイン</button>
</div>
<Counter />
</div>
</template>
<script setup>
import Counter from './Counter.vue'
import { useUserStore } from '../stores/user'
const user = useUserStore()
</script>
状態の永続化
永続化プラグインを導入することで、localStorageに状態を保存できます:
npm install pinia-plugin-persistedstate
プラグインの設定:
// main.js
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import piniaPersist from 'pinia-plugin-persistedstate'
import App from './App.vue'
const app = createApp(App)
const pinia = createPinia()
pinia.use(piniaPersist)
app.use(pinia)
app.mount('#app')
ストアの永続化設定:
// stores/counter.js
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => ({
currentCount: 0
}),
actions: {
increment() {
this.currentCount++
}
},
persist: true
})