〰️

Pinia で Store の状態を利用した外部モジュールの作成時には getActivePinia() 関数を使おう🍍

2024/11/26に公開

はじめに

こんにちは、からころです。
今回は、Vue.js で Pinia🍍 を利用する際に、Store の 状態を利用して、値を返却するなどの関数を作成する場合に、安全に Store を扱うための小技を紹介します。

具体例

以下のような、Pinia で作成された Store モジュールがあったとします。
この Store モジュールは、ユーザー情報を保持しておく用途で使用されそうですね。

user.ts
import { defineStore, acceptHMRUpdate } from 'pinia'
import { ref } from 'vue'

interface UserInfo {
  id: string
  name: string
  address: string
  phoneNumber: string
  birthDate: string
}

export const useUserStore = defineStore('user', () => {
  const userInfo = ref<UserInfo | undefined>()

  function setUserInfo(userInfo: info): void {
    userInfo.value = info
  }

  return {
    userInfo,
    setUserInfo,
  }
})

if (import.meta.hot) {
  import.meta.hot.accept(acceptHMRUpdate(useUserStore, import.meta.hot))
}

例えば、userInfo.ts で定義されているStoreの状態を一部だけ取得するような関数を作成したい場合、下記の2つの選択肢が考えられます。

  1. Composablesとして切り出す
  2. 外部モジュールとして切り出す

今回は、二つ目の選択肢の Store の 状態を外部モジュールとして切り出す 場合について考えようと思います。

Store の状態を外部モジュールに切り出す際の問題点

Store の状態を Composables ではない、外部モジュールに切り出す場合、Store 初期化前に Store を呼び出すと、下記のようなエラーが出力されるという問題点があります。

これでは安全にモジュール化できているとは言えません。

解決方法

タイトルにもある通りですが、getActivePinia() 関数を利用しましょう。
下記のように、getActivePinia() を利用して、Pinia の インスタンスが有効かどうかを判定することができ、Composablesではない外部モジュールで Store の状態を利用する場合でも、安全にモジュール化することができます。

module.ts
import { getActivePinia } from 'pinia'
import { useUserStore } from './user.ts'

export function getUserInfo() {
  // Pinia インスタンスの有効判定
  const isPiniaActive = !!getActivePinia()
  if (!isPiniaActive) {
    return {
      userId: ''
      userName: '',
    }
  }
  const user = useUserStore()
  return {
    userId: user.userInfo?.id || '',
    userName: user.userInfo?.name || '',
  }
}

おわりに

今回は、意外に知らない人が多そうな Pinia の機能を紹介しました。
指摘・コメントなどあればお気軽にお願いします!

Vue・Nuxt 情報が集まる広場 / Plaza for Vue・Nuxt.

Discussion