Composing Stores
Composing stores is about having stores that use each other and there is one rule to follow:
If two or more stores use each other, they cannot create an infinite loop through getters or actions. They cannot both directly read each other state in their setup function:
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
Note that if one store uses another store, there is no need to create a new store in a separate file, you can directly import it. Think of it as nesting.
You can call useOtherStore()
at the top of any getter or action:
import { useUserStore } from "./user"
export const cartStore = defineStore("cart", {
getters: {
// ... other getters
summary(state) {
const user = useUserStore()
return `Hi ${user.name}, you have ${state.list.length} items in your cart. It costs ${state.price}.`
}
},
actions: {
purchase() {
const user = useUserStore()
return apiPurchase(user.id, this.list)
}
}
})
Shared Getters
You can simply call useOtherStore()
inside a getter:
import { defineStore } from "react-mise"
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
The same applies to actions:
import { defineStore } from "react-mise"
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)
}
}
}
})