1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ひとりアドカレ2024 byもんすんAdvent Calendar 2024

Day 25

VuexからPiniaへの移行:クリスマスに見直す状態管理

Last updated at Posted at 2024-12-24

導入

こんにちは、もんすんです!

私の個人アドカレであるひとりアドカレ2024 byもんすん Advent Calendar 2024の25記事目をお届けいたします🎄

ついに最終回となります。。

私が担当していたプロジェクトでは、Nuxt3をベースに開発されているものがありました。
元々は状態管理にVuexを採用していましたが、最新のプロジェクト要件や技術トレンドに対応するため、Piniaに移行しました。
今回はPiniaへの切り替えについて紹介していきます。

VuexとPinia

なぜVuexを利用していたか

VuexはVue.js公式の状態管理ライブラリであり、長年にわたってVueエコシステムの中核的な存在として活用されてきました。
当プロジェクトでも、当時ドキュメントが充実しており、コミュニティも活発であったことから、プロジェクト初期においては安定性と信頼性が重視され、選択されました。

なぜPiniaに乗り換えたか

プロジェクトを進めていく中で、Vuexのいくつかの課題や、Piniaの新しい利点が浮き彫りになり、移行を検討することになりました。

PiniaはVue3とそのComposition APIを念頭に設計されています。
Vuexと比較してAPIが直感的でシンプルです。
特に、ステート、ゲッター、アクションの定義が簡潔になり、コード量が大幅に削減されました。

また、Vue3の登場により、Vueエコシステム全体が進化しています。
その中で、Piniaは公式に推奨される状態管理ライブラリとなり、今後の標準となる可能性が高いと判断しました。

Piniaに乗り換え手順

パッケージのインストール

以下のコマンドを実行します。
私のプロジェクトでは、データをSessionStorageに保持したかったため、pinia-plugin-persistedstateを入れていますが、なくてもpiniaを利用することは可能です。

npm i pinia @pinia/nuxt pinia-plugin-persistedstate

ソースコードの変更

では、ソースコードの変更です。
Vuexを利用していた時は、モジュール用のソースの他に、accessorstore/index.tsという全Storeデータをまとめた処理も実装していました。

Vuex(変更前)

  • モジュール
import { Module, VuexModule, Action, Mutation } from 'vuex-module-decorators'
export const COUNT_MODULE = 'CountModule'

import { inject } from 'vue'

@Module({
  name: COUNT_MODULE,
  namespaced: true,
  stateFactory: true,
})
export default class CountModule extends VuexModule {

  private count =  0

  get getCount() {
    return this.count
  }

  @Mutation
  public resetCount() {
    this.count =  0
  }

  @Action
  public fetchCount(){
    // 非同期でのCount取得処理など
    GetCountService.get().then((count) => {
	    this.count = count
    })
  }
}

  • accessor.ts
import { Store } from 'vuex'
import { getModule } from 'vuex-module-decorators'
import CountModule from '~/store/count-module'

let countStore: CountModule

function initializeStores(sessionStore: Store<any>, localStore: Store<any>): void {
  countStore = getModule(CountModule, sessionStore)
}

export {
  initializeStores,
  countStore,
}
  • store/index.ts
import { Store } from 'vuex'
import { initializeStores } from '~/store/accessor'
import CountModule, { COUNT_MODULE } from './count-module'
import VuexPersist from 'vuex-persist'

const vuexSessionStorage = new VuexPersist({
  key: 'vuex',
  storage: window.sessionStorage,
  modules: [
    UNREAD_MESSAGE_COUNT_MODULE_NAME,
  ],
})

const sessionStore = new Store({
  modules: {
    CountModule,
  },
  plugins: [
    vuexSessionStorage.plugin,
  ],
})

const initializer = (sessionStore: Store<any>) => initializeStores(sessionStore)
initializer(sessionStore)
export const plugins = [initializer]
export * from '~/store/accessor'

Pinia(変更後)

import { defineStore } from 'pinia'
import { inject, ref } from 'vue'

export const useCountStore = defineStore('CountStore', () => {

  const count = ref(0)

  const resetCount = () => {
    count.value =  0
  }

  const fetchCount = () => {
    // 非同期でのCount取得処理など
    GetCountService.get().then((newCount) => {
	    count.value = newCount
    })
  }

  return {
    count,
    resetCount,
    fetchCount,
  }
}, {
  persist: {
    storage: sessionStorage,
  }
})

Piniaの方がかなりシンプルに記述できていることかと思います。

最後に

Piniaへの移行は、コードのシンプルさだけでなく、開発体験の向上やメンテナンス性の向上にも大きく寄与しました。
Piniaの導入はスムーズでありながら、Vue3に最適化されたモダンなアプローチを提供してくれます。

ぜひ、みなさんのプロジェクトでもPiniaを試してみてください!

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?