Almacenes de composición
Componer almacenes consiste en tener almacenes que se utilicen mutuamente, y esto está soportado en Pinia. Hay una regla a seguir:
Si dos o más almacenes se utilizan entre sí, no pueden crear un bucle infinito a través de getters o acciones. No pueden ambos leer directamente el estado del otro en su función de configuración:
const useX = defineStore('x', () => {
const y = useY()
// ❌ Esto no es posible porque y también intenta leer x.name
y.name
function doSomething() {
// ✅ Leer y propiedades computadas o acciones
const yName = y.name
// ...
}
return {
name: ref('I am X'),
}
})
const useY = defineStore('y', () => {
const x = useX()
// ❌ Esto no es posible porque x también intenta leer y.name
x.name
function doSomething() {
// ✅ Leer x propiedades computadas o acciones
const xName = x.name
// ...
}
return {
name: ref('I am Y'),
}
})
const useX = defineStore('x', () => {
const y = useY()
// ❌ Esto no es posible porque y también intenta leer x.name
y.name
function doSomething() {
// ✅ Leer y propiedades computadas o acciones
const yName = y.name
// ...
}
return {
name: ref('I am X'),
}
})
const useY = defineStore('y', () => {
const x = useX()
// ❌ Esto no es posible porque x también intenta leer y.name
x.name
function doSomething() {
// ✅ Leer x propiedades computadas o acciones
const xName = x.name
// ...
}
return {
name: ref('I am Y'),
}
})
Almacenes anidados
Ten en cuenta que si un almacén utiliza otro almacén, puedes importar directamente y llamar a la función useStore()
dentro de acciones y getters. Entonces puedes interactuar con el almacén como lo harías desde dentro de un componente Vue. Ver Getters Compartidos y Acciones Compartidas.
Cuando se trata de establecer almacenes, simplemente puedes usar una de los almacenes en la parte superior de la función del almacén:
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 in your cart. It costs ${price.value}.`
})
function purchase() {
return apiPurchase(user.id, this.list)
}
return { summary, purchase }
})
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 in your cart. It costs ${price.value}.`
})
function purchase() {
return apiPurchase(user.id, this.list)
}
return { summary, purchase }
})
Getters Compartidos
Puedes simplemente llamar a useOtherStore()
dentro de un getter:
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}.`
},
},
})
Acciones Compartidas
Lo mismo ocurre con las acciones:
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)
// otra acción
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)
// otra acción
this.emptyCart()
} catch (err) {
displayError(err)
}
},
},
})
Como las acciones pueden ser asíncronas, asegúrate que todas las llamadas a useStore()
aparezcan antes de cualquier await
. De lo contrario, esto puede llevar a usar una instancia incorrecta de pinia en aplicaciones SSR:
import { defineStore } from 'pinia'
import { useUserStore } from './user'
export const useCartStore = defineStore('cart', {
actions: {
async orderCart() {
// ✅ llamada en la parte superior de la acción antes de
// cualquier `await`
const user = useUserStore()
try {
await apiOrderCart(user.token, this.items)
// ❌ llamada después de una sentencia `await`
const otherStore = useOtherStore()
// otra acción
this.emptyCart()
} catch (err) {
displayError(err)
}
},
},
})
import { defineStore } from 'pinia'
import { useUserStore } from './user'
export const useCartStore = defineStore('cart', {
actions: {
async orderCart() {
// ✅ llamada en la parte superior de la acción antes de
// cualquier `await`
const user = useUserStore()
try {
await apiOrderCart(user.token, this.items)
// ❌ llamada después de una sentencia `await`
const otherStore = useOtherStore()
// otra acción
this.emptyCart()
} catch (err) {
displayError(err)
}
},
},
})