Skip to content
On this page

Composing Stores {#composing-stores}

ストアを構成するということは、お互いに利用し合うストアを持つことであり、Pinia ではこれをサポートしています。守るべきルールは 1 つです:

2 つ以上のストアがお互いを使用する 場合、ゲッターアクション によって無限ループを作ることはできません。また、セットアップ関数で 互いの 状態を直接読み取ることもできません:

js
const useX = defineStore('x', () => {
  const y = useY()

  // ❌ This is not possible because y also tries to read x.name
  y.name

  function doSomething() {
    // ✅ Read y properties in computed or actions
    const yName = y.name
    // ...
  }

  return {
    name: ref('I am X'),
  }
})

const useY = defineStore('y', () => {
  const x = useX()

  // ❌ This is not possible because x also tries to read y.name
  x.name

  function doSomething() {
    // ✅ Read x properties in computed or actions
    const xName = x.name
    // ...
  }

  return {
    name: ref('I am Y'),
  }
})
const useX = defineStore('x', () => {
  const y = useY()

  // ❌ This is not possible because y also tries to read x.name
  y.name

  function doSomething() {
    // ✅ Read y properties in computed or actions
    const yName = y.name
    // ...
  }

  return {
    name: ref('I am X'),
  }
})

const useY = defineStore('y', () => {
  const x = useX()

  // ❌ This is not possible because x also tries to read y.name
  x.name

  function doSomething() {
    // ✅ Read x properties in computed or actions
    const xName = x.name
    // ...
  }

  return {
    name: ref('I am Y'),
  }
})

ネストしたストア {#nested-stores}

あるストアが別のストアを使用する場合、アクションゲッター 内で useStore() 関数を直接インポートして呼び出すことができることに注意してください。そうすると、Vue コンポーネント内から操作するのと同じように、ストアを操作することができます。共有ゲッター共有アクション を参照してください。

ストアの設定 に関しては、ストア機能の 上部にある ストアのいずれかを使用すればよいだけです。

ts
import { useUserStore } from './user'

export const useCartStore = defineStore('cart', () => {
  const user = useUserStore()

  const summary = computed(() => {
    return `Hi ${user.name}, you have ${state.list.length} items in your cart. It costs ${state.price}.`
  })

  function purchase() {
    return apiPurchase(user.id, this.list)
  }

  return { summary, purchase }
})
import { useUserStore } from './user'

export const useCartStore = defineStore('cart', () => {
  const user = useUserStore()

  const summary = computed(() => {
    return `Hi ${user.name}, you have ${state.list.length} items in your cart. It costs ${state.price}.`
  })

  function purchase() {
    return apiPurchase(user.id, this.list)
  }

  return { summary, purchase }
})

共有ゲッター {#shared-getters}

ゲッター の中で useOtherStore() を呼び出すだけです:

js
import { defineStore } from 'pinia'
import { useUserStore } from './user'

export const useCartStore = defineStore('cart', {
  getters: {
    summary(state) {
      const user = useUserStore()

      return `Hi ${user.name}, you have ${state.list.length} items in your cart. It costs ${state.price}.`
    },
  },
})
import { defineStore } from 'pinia'
import { useUserStore } from './user'

export const useCartStore = defineStore('cart', {
  getters: {
    summary(state) {
      const user = useUserStore()

      return `Hi ${user.name}, you have ${state.list.length} items in your cart. It costs ${state.price}.`
    },
  },
})

共有アクション {#shared-actions}

アクション も同様です:

js
import { defineStore } from 'pinia'
import { useUserStore } from './user'

export const useCartStore = defineStore('cart', {
  actions: {
    async orderCart() {
      const user = useUserStore()

      try {
        await apiOrderCart(user.token, this.items)
        // another action
        this.emptyCart()
      } catch (err) {
        displayError(err)
      }
    },
  },
})
import { defineStore } from 'pinia'
import { useUserStore } from './user'

export const useCartStore = defineStore('cart', {
  actions: {
    async orderCart() {
      const user = useUserStore()

      try {
        await apiOrderCart(user.token, this.items)
        // another action
        this.emptyCart()
      } catch (err) {
        displayError(err)
      }
    },
  },
})

アクションは非同期に実行されるので、全ての useStore() の呼び出しが await の前にあること を確認してください。そうしないと、SSR アプリ で間違った pinia インスタンスを使用してしまう可能性があります。

js
import { defineStore } from 'pinia'
import { useUserStore } from './user'

export const useCartStore = defineStore('cart', {
  actions: {
    async orderCart() {
      // ✅ call at the top of the action before any `await`
      const user = useUserStore()

      try {
        await apiOrderCart(user.token, this.items)
        // ❌ called after an `await` statement
        const otherStore = useOtherStore()
        // another action
        this.emptyCart()
      } catch (err) {
        displayError(err)
      }
    },
  },
})
import { defineStore } from 'pinia'
import { useUserStore } from './user'

export const useCartStore = defineStore('cart', {
  actions: {
    async orderCart() {
      // ✅ call at the top of the action before any `await`
      const user = useUserStore()

      try {
        await apiOrderCart(user.token, this.items)
        // ❌ called after an `await` statement
        const otherStore = useOtherStore()
        // another action
        this.emptyCart()
      } catch (err) {
        displayError(err)
      }
    },
  },
})

Released under the MIT License.