javascript - ¿Cuál es la forma común de encapsular datos dentro de los store de Pinia al usar la API de composición?
Estoy usando Vue 3 con Pinia y quiero usar la API de composición dentro de mis stores de Pinia. Dado el siguiente ejemplo de store
export const useMyStore = defineStore("my", () => {
const currentState = ref(0);
return { currentState };
}
);
Puedo modificar directamente el valor de currentState. No estoy seguro de si este es el camino a seguir o si debería prevenir esto y proporcionar algunas funciones get y set como
export const useMyStore = defineStore("my", () => {
const currentState = ref(false);
const readonlyCurrentState = computed((): Readonly<boolean> => currentState.value);
function changeState(newState: boolean) {
currentState.value = newState;
}
return { readonlyCurrentState, changeState };
}
);
La API de opciones resuelve mi problema proporcionando getters y acciones, así que pensé si debería lograr lo mismo aquí.
Esto podría ser una pregunta basada en opiniones, pero me gustaría saber si debería encapsular el estado currentState para evitar su corrupción por accidente.
Respuesta #1
Puedo modificar directamente el valor de
currentState
Sí, esto es intencional. Como se describe en la comparación con Vuex
las mutaciones ya no existen. A menudo se percibían como extremadamente verbosas. Inicialmente trajeron la integración con devtools, pero eso ya no es un problema.
Esta es una razón más técnica, pero puedes leer más del propio autor (y de personas a las que no les gusta esta nueva "libertad") en esta discusión: Agregar una opción para no permitir la modificación directa del estado desde el componente
En general, el código en tu pregunta demuestra el punto perfectamente: mucho código innecesario solo para cambiar un valor booleano simple. Por supuesto, hay casos donde los datos son más complejos, quieres hacer cumplir algunas restricciones, etc., donde la mutación directa sin restricciones puede considerarse peligrosa. Creo que el patrón en tu pregunta es perfectamente viable y puedes encontrar más ideas (y soporte experimental de “modo estricto” a la espera de comentarios) en la discusión enlazada.
Personalmente, creo que muchos de los controles de seguridad se pueden hacer con linting y especialmente con definiciones de TypeScript. Obtienes la seguridad adicional durante el desarrollo sin pagar el precio en tiempo de ejecución (en términos de código adicional ejecutándose y siendo empaquetado y servido). Lo genial de Pinia es que nos da la opción de cómo abordar el problema...
Respuesta #2
En un caso donde realmente quieras restringir el acceso a los datos, lamentablemente no se recomienda tu segundo enfoque. Los documentos de Pinia dicen:
Debes devolver todas las propiedades del estado en los stores de setup para que Pinia las reconozca como estado. En otras palabras, no puedes tener propiedades de estado privadas en los stores.
Para solucionar eso, el blog Mastering Pinia sugiere crear una segunda tienda "privada" que sea referenciada (pero no expuesta) por la primera. Para ampliar tu ejemplo:
// This new store is not exported
const useMyPrivateStore = defineStore('my-private', () => {
const currentState = ref(false);
return { currentState }
})
export const useMyStore = defineStore("my", () => {
// You can use stores within stores
const privateState = useMyPrivateStore()
const readonlyCurrentState = computed(() => privateState.currentState);
const changeState = (newState: boolean) => privateState.currentState = newState;
return { readonlyCurrentState, changeState };
}
);
