Files
fuel-price/.agents/skills/pinia/references/features-composing-stores.md
Ovidiu U 4a3ce4cc1d
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (8.3) (push) Has been cancelled
tests / ci (8.4) (push) Has been cancelled
tests / ci (8.5) (push) Has been cancelled
docs: add advanced skills for Vitest, Pinia, and Vue built-ins
Add comprehensive reference documentation for:
- Vitest: environments, projects/workspaces, type testing, vi utilities
- Pinia: HMR, Nuxt integration, SSR setup
- Vue: built-in components (Transition, Teleport, Suspense, KeepAlive) and advanced directives
2026-04-11 16:28:36 +01:00

2.6 KiB

name, description
name description
composing-stores Store-to-store communication and avoiding circular dependencies

Composing Stores

Stores can use each other for shared state and logic.

Rule: Avoid Circular Dependencies

Two stores cannot directly read each other's state during setup:

// ❌ Infinite loop
const useX = defineStore('x', () => {
  const y = useY()
  y.name // Don't read here!
  return { name: ref('X') }
})

const useY = defineStore('y', () => {
  const x = useX()
  x.name // Don't read here!
  return { name: ref('Y') }
})

Solution: Read in getters, computed, or actions:

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

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

  return { name: ref('X'), doSomething }
})

Setup Stores: Use Store at Top

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

export const useCartStore = defineStore('cart', () => {
  const user = useUserStore()
  const list = ref([])

  const summary = computed(() => {
    return `Hi ${user.name}, you have ${list.value.length} items`
  })

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

  return { list, summary, purchase }
})

Shared Getters

Call useStore() inside a getter:

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`
    },
  },
})

Shared Actions

Call useStore() inside an action:

import { useUserStore } from './user'
import { apiOrderCart } from './api'

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

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

SSR: Call Stores Before Await

In async actions, call all stores before any await:

actions: {
  async orderCart() {
    // ✅ All useStore() calls before await
    const user = useUserStore()
    const analytics = useAnalyticsStore()

    try {
      await apiOrderCart(user.token, this.items)
      // ❌ Don't call useStore() after await (SSR issue)
      // const otherStore = useOtherStore()
    } catch (err) {
      displayError(err)
    }
  },
}

This ensures the correct Pinia instance is used during SSR.