--- name: composing-stores description: 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: ```ts // ❌ 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: ```ts 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 ```ts 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: ```ts 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: ```ts 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`: ```ts 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.