Files
agent-skills/skills/pinia/references/features-composing-stores.md
Jason Woltje f5792c40be feat: Complete fleet — 94 skills across 10+ domains
Pulled ALL skills from 15 source repositories:
- anthropics/skills: 16 (docs, design, MCP, testing)
- obra/superpowers: 14 (TDD, debugging, agents, planning)
- coreyhaines31/marketingskills: 25 (marketing, CRO, SEO, growth)
- better-auth/skills: 5 (auth patterns)
- vercel-labs/agent-skills: 5 (React, design, Vercel)
- antfu/skills: 16 (Vue, Vite, Vitest, pnpm, Turborepo)
- Plus 13 individual skills from various repos

Mosaic Stack is not limited to coding — the Orchestrator and
subagents serve coding, business, design, marketing, writing,
logistics, analysis, and more.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 16:27:42 -06: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.