5
2

More than 1 year has passed since last update.

[Vue]VuexからPiniaへ移行

Last updated at Posted at 2023-08-10

はじめに

  • プロジェクトでVuexをPiniaへ移行する作業を行ったのでその作業手順メモ。

  • store数が多かったので、VuexとPiniaを並行導入しつつ、段階的にPiniaへ移行した。

  • 基本的にはマイグレーションガイドを見れば問題なかった。

移行手順の記録

piniaのインストール

yarn add pinia

main.tsの設定

  • createPinia()を追加する。並行稼働するため、Vuexのstore設定も残す
  • VuexはDynamicImportをするために、store/index.tsで空storeを作成してる
  • PiniaではDynamicImportの設定は不要(必要な時に作られる)なので、storeの初期化不要。
main.ts
import store from '@/store' // Vuexのstore初期化ファイル。
+ import { createPinia } from 'pinia'
...
app.use(store)
+ app.use(createPinia())
...

storesフォルダにstoreファイルを作成

  • Vuexはstoreフォルダ(sなし)で別で管理できるので、並行稼動ができる。
  • setup構文が使えるので、stateはref関数、getterはcomputed、actionは関数で定義できる。
    • ※なお、mutationは存在せず、actionに含める。
  • 名称はuseXXXとし、composition-apiとして配布する。
  • 以下、before, after例。なお、beforeはvuex-module-decorators記法で記載。通常のVuex記法はマイグレーションガイドに記載されているので、そちらを参照。
    • ※vuex-module-decorators:クラス構文と専用のデコレータでvuexの定義が行える。クラスの恩恵が受けれるため、型定義などがしやすい。が、関数型プログラミンが主流となったことで利用されなくなった。(現在メンテされていない)
before(vuex-module-decorators記法)
import { VuexModule, Module, Action, Mutation, getModule } from 'vuex-module-decorators'
import store from '@/store'

export interface ICompany {
  id: string
  name: string
}

// DynamicImportの設定
@Module({ dynamic: true, store, name: 'company' })
class Company extends VuexModule implements ICompany {
  // stateはフィールド
  public id = ''
  public name = ''
  
  // getter
  get comanyIdName() {
    return `${this.id}:${this.name}`
  }

  @Mutation
  private SET_COMPANY(company: ICompany) {
    this.id = company.id
    this.name = company.name
  }

 // アノテーションで設定する
  @Action
  public setCompany(company: ICompany) {
    this.SET_COMPANY(company)
  }
}

export const CompanyModule = getModule(Company)

after(Pinia-setup記法)

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

export interface ICompany {
  id: string
  name: string
}

export const useCompanyStore = defineStore('company', () => {
  // stateはref変数
  const id = ref('')
  const name = ref('')

  // gettterはcomputed
  const companyIdName =computed(()=> `${id.value}:${name.value}`)

  // actionはmutationと統合して、関数
  const setCompany = (company: ICompany) => {
    id.value = company.id
    name.value = company.name
  }

  return { id, name, companyIdName, setCompany }
})

  • ちなみに、returnするものが多い場合は、定義時に関数化してまとめるとよい。
export const useUserStore = defineStore('XXX', () => {

  const useUserState = () => {
    return {
      name: ref(''),
      email: ref(''),
      ...
    }
  }
  const userState = useUserState()

  const useComputables = () => {
    return {
      isUser: computed(() => XXXX),
      isCompany: computed(() => XXXX),
      ...
    }
  }
  const computables = useComputables()

  return { ...userState, ...computables }

利用側の修正

  • 作成したuse関数を使用し、利用箇所を置き換えるだけ。
- import { CompanyModule } from '@/store/modules/company'
+ import { useCompanyStore } from '@/stores/company'

// use関数を使用する。(変数名も同じ(CompanyModule)にすれば実質変更はここだけ。)
+ const companyStore = useCompanyStore()

...
-  CompanyModule.setCompany({
+  companyStore.setCompany({
    name: item.name,
    id: item.id
  })
- const id = companyModule.id
+ const id = companyStore.id

  • tsファイルの場合、topレベルで呼び出すとundefindeになってしまうので、関数内で取得する
    • ここで、はまってしまった。がよく考えれば、script setupdefineComponent関数のシンタックスシュガーだったから、関数内で取得しているのか。
    • 公式の移行手順に思いっきり書かれてた。。。

Vuexの削除

  • すべての動作確認が終わり、移行が問題なければ、Vuexの資材を削除する。
    • storeフォルダの削除
    • main.tsの設定削除
main.ts
- import store from '@/store' // Vuexのstore初期化ファイル。
...
- app.use(store)
...
  • 最後に、Vuexをアインストールして作業完了
    • package.jsonフォルダ直下で以下を実行
yarn remove vuex
yarn remove vuex-module-decorators
  • 念のためキャッシュクリア、node_module入れ替えを行い(以下)、動作を再度確認した。
rm -rf node_modules
yarn cache clean 
yarn install

おわりに

  • 移行は、他のVu3系ライブラリに比べて格段に簡単だった。
  • mutationがなくなったこと、setup構文で記載できることで、非常に簡潔にかけるようになった。
  • Vuexで問題視されていた、複雑な型定義も解消されたので、Pinia移行は非常におすすめ。
    • ※複雑な型定義問題で、vuex-module-decoratorsを使用する経緯となっった。
5
2
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
5
2