🍍

Vuex の新しいライバル? Pinia のご紹介

2021/04/08に公開

Pinia は Vue.js 向けの状態管理ライブラリです。
昨年に知ったときは「experimental なプロジェクト」という注意書きがあったのですが、先月にその表記がなくなっていたので少し触ってみました。
(ちなみにスペイン語でパイナップルの意味だそうです)

https://pinia.esm.dev/

ストア定義

下記は GitHub の README から引用したコードで、一部コメントを翻訳してあります。

import { defineStore } from 'pinia'

export const useMainStore = defineStore({
  // ストアの名前
  id: 'main',
  // 初期状態を返す関数
  state: () => ({
    counter: 0,
    name: 'Eduardo',
  }),
  getters: {
    doubleCount() {
      return this.counter * 2
    },
    // ゲッターの中で他のゲッターを使う
    doubleCountPlusOne() {
      return this.doubleCount * 2 + 1
    },
  },
  actions: {
    reset() {
      // `this` はストアのインスタンス
      this.counter = 0
    },
  },
})

大まかには Vuex と似ていて、以下の 2 点が主な違いです。

  • ストアの内容を this で取得すること
  • mutations がなく action 内で state の値を直接変更できること

個人的に Vuex の mutations はボイラープレート感が強いと思っていたので、直接変更できるのは良いですね。

もちろん型の補完も効きます。
image

ストア呼び出し

こちらも README からの引用です。

import { useMainStore } from '@/stores/main'

export default defineComponent({
  setup() {
    const main = useMainStore()

    return {
      // ストア全体のアクセス
      main,
      // 特定の state へのアクセス
      state: computed(() => main.counter),
      // 特定のゲッターへのアクセス
      doubleCount: computed(() => main.doubleCount),
    }
  },
})

呼び出し方もほぼ Vuex と同じです。
先程 export した use- 関数でストアを取得して、state や getters の値は computed でラップします。
Vuex だと store.state.counter のようになりますが、Pinia はストアに直接プロパティがはえています。
(コードにはないですが)action も main.reset() のようにメソッドとして呼び出せるので便利です。

まとめ

以前から typed-vuex というラッパーライブラリを使用していたので、よく言われる「Vuex は型が聞かなくてつらい」ということはなかったのですが、大量の mutations を書く必要があったりするとつらいです。
その点 Pinia はコードの量が少なくて使いやすいです。ただし、ストアの外でも値を直接書き換えることができてしまう(main.counter = 1 とか)ので、そこは欠点に感じるかも知れません(大規模な開発には向いてなさそう)。
今後イミュータブルにするオプションなどがつくといいのですが。

また、Vuex5 の RFC が先日発表されました。mutations がなくなるなど Pinia のように使いやすくなりそうなので、Vuex の動向にも注目していきたいと思います。

Discussion