Stores básicos
create fabrica un hook con el store enganchado: getState, setState, subscribe. Dentro, set y get actualizan y leen.
Documentación: create, TypeScript.
create, set, get
import { create } from 'zustand'
export const useCarritoStore = create((set, get) => ({
lineas: [],
anadir: (id) =>
set((state) => ({
lineas: [...state.lineas, { id, cantidad: 1 }],
})),
vaciar: () => set({ lineas: [] }),
totalUnidades: () =>
get().lineas.reduce((n, l) => n + l.cantidad, 0),
}))set({ lineas: [] })— objeto: merge superficial con el state actual.set((state) => ({ … }))— función: lees el state fresco (clicks rápidos, async).get()— lees sin suscribirte (acciones, no componentes).
set no hace deep merge. set({ user: { nombre: 'Ana' } }) sustituye user entero. Nested:
set((state) => ({
usuario: {
...state.usuario,
nombre: 'Ana',
},
}))Arrays: nuevo array (map, filter, spread). No state.lineas.push(...) sobre el array del store. Immer es opcional (capítulo 5), no un requisito.
set(next, true) reemplaza el state (el segundo argumento replace). Útil al resetear; peligroso si olvidas acciones.
TypeScript (forma actual)
La forma currificada create<T>()((set) => …) es la recomendada para inferir middleware:
type CarritoStore = {
lineas: { id: string; cantidad: number }[]
anadir: (id: string) => void
}
export const useCarritoStore = create<CarritoStore>()((set) => ({
lineas: [],
anadir: (id) =>
set((state) => ({
lineas: [...state.lineas, { id, cantidad: 1 }],
})),
}))El resto del manual usa JS cuando simplifica; los snippets TS siguen este patrón.
Inmutabilidad
El store notifica si la referencia de lo seleccionado cambia (Object.is en v5). Mutar state.lineas[0].cantidad++ sin set no dispara bien a los suscriptores. Siempre set / setState.
Errores habituales
- Creer que
set({ user: { … } })conservauser.email. - Guardar
totalUnidadesen el state en vez de calcularlo (capítulo 3). - Import default
create: en v5 los defaults se eliminaron; usaimport { create }.
Buenas prácticas
- Estado plano cuando puedas; spread consciente si anidas.
- Acciones de dominio (
anadir,vaciar), no veintesetCantidad1sueltos.
Ejercicio
- Implementa
cambiarCantidad(id, n)sin mutarlineas. - Llama
anadirdos veces seguidas y comprueba que no pisa la primera línea. - Tipa el store con
create<CarritoStore>().
Siguiente paso
Continúa con Selectores y rendimiento.
