Skip to content
On this page

コンポーザブルへの対応

コンポーザブル は、Vue Composition APIを利用して、ステートフルなロジックをカプセル化して再利用するための関数です。自分で書くか、外部ライブラリ を使用するか、またはその両方を行うかにかかわらず、pinia ストアで Composables の力を十分に活用することができます。

Option ストア

Option ストアを定義する場合、state プロパティの内部でコンポーザブルを呼び出すことができます:

ts
export const useAuthStore = defineStore('auth', {
  state: () => ({
    user: useLocalStorage('pinia/auth/login', 'bob'),
  }),
})
export const useAuthStore = defineStore('auth', {
  state: () => ({
    user: useLocalStorage('pinia/auth/login', 'bob'),
  }),
})

書き込み可能なステートしか返せない(例: ref())ことに留意してください。以下に、使用できるコンポーザブルの例を示します:

ここでは、Option ストアで使用できない(Setup ストアでは使用できる)コンポーザブルの例を紹介します:

Setup ストア

一方、Setup ストアの定義では、すべてのプロパティがステート、アクション、ゲッターに区別されるため、ほぼすべてのコンポーザブルを使用することができます:

ts
import { defineStore, skipHydrate } from 'pinia'
import { useMediaControls } from '@vueuse/core'

export const useVideoPlayer = defineStore('video', () => {
  // we won't expose this element directly
  const videoElement = ref<HTMLVideoElement>()
  const src = ref('/data/video.mp4')
  const { playing, volume, currentTime, togglePictureInPicture } =
    useMediaControls(video, { src })

  function loadVideo(element: HTMLVideoElement, src: string) {
    videoElement.value = element
    src.value = src
  }

  return {
    src,
    playing,
    volume,
    currentTime,

    loadVideo,
    togglePictureInPicture,
  }
})
import { defineStore, skipHydrate } from 'pinia'
import { useMediaControls } from '@vueuse/core'

export const useVideoPlayer = defineStore('video', () => {
  // we won't expose this element directly
  const videoElement = ref<HTMLVideoElement>()
  const src = ref('/data/video.mp4')
  const { playing, volume, currentTime, togglePictureInPicture } =
    useMediaControls(video, { src })

  function loadVideo(element: HTMLVideoElement, src: string) {
    videoElement.value = element
    src.value = src
  }

  return {
    src,
    playing,
    volume,
    currentTime,

    loadVideo,
    togglePictureInPicture,
  }
})

SSR

Server Side Rendering を扱う場合、ストア内でコンポーザブルを使用するために、いくつかの追加手順を行う必要があります。

Option ストア では、hydrate() 関数を定義する必要があります。この関数は、ストアがクライアント(ブラウザ)上でインスタンス化されるとき、ストアが作成された時点で利用可能な初期状態がある場合に呼び出されます。この関数を定義する必要があるのは、このようなシナリオでは state() が呼び出されないからです。

ts
import { defineStore, skipHydrate } from 'pinia'
import { useLocalStorage } from '@vueuse/core'

export const useAuthStore = defineStore('auth', {
  state: () => ({
    user: useLocalStorage('pinia/auth/login', 'bob'),
  }),

  hydrate(state, initialState) {
    // in this case we can completely ignore the initial state since we
    // want to read the value from the browser
    state.user = useLocalStorage('pinia/auth/login', 'bob')
  },
})
import { defineStore, skipHydrate } from 'pinia'
import { useLocalStorage } from '@vueuse/core'

export const useAuthStore = defineStore('auth', {
  state: () => ({
    user: useLocalStorage('pinia/auth/login', 'bob'),
  }),

  hydrate(state, initialState) {
    // in this case we can completely ignore the initial state since we
    // want to read the value from the browser
    state.user = useLocalStorage('pinia/auth/login', 'bob')
  },
})

Setup ストア では、初期状態からピックアップされるべきではないステートのプロパティに対して skipHydrate() という名前のヘルパーを使用する必要があります。Option ストアとは異なり、Setup ストアは単に state() の呼び出しをスキップ することはできませんので、skipHydrate() でハイドレートできないプロパティをマークします。これは書き込み可能なリアクティブプロパティにのみ適用されることに注意してください:

ts
import { defineStore, skipHydrate } from 'pinia'
import { useEyeDropper, useLocalStorage } from '@vueuse/core'

export const useColorStore = defineStore('colors', () => {
  const { isSupported, open, sRGBHex } = useEyeDropper()
  const lastColor = useLocalStorage('lastColor', sRGBHex)
  // ...
  return {
    lastColor: skipHydrate(lastColor), // Ref<string>
    open, // Function
    isSupported, // boolean (not even reactive)
  }
})
import { defineStore, skipHydrate } from 'pinia'
import { useEyeDropper, useLocalStorage } from '@vueuse/core'

export const useColorStore = defineStore('colors', () => {
  const { isSupported, open, sRGBHex } = useEyeDropper()
  const lastColor = useLocalStorage('lastColor', sRGBHex)
  // ...
  return {
    lastColor: skipHydrate(lastColor), // Ref<string>
    open, // Function
    isSupported, // boolean (not even reactive)
  }
})

Released under the MIT License.