¡Claro que sí! Zustand es una librería de gestión de estados para React (y vainilla JavaScript) conocida por su simplicidad, ligereza y rendimiento. Es una alternativa popular para quienes buscan una solución menos “opinionated” y con menos boilerplate que Redux.

Aquí tienes un “cheatsheet” completo y bien estructurado de Zustand, optimizado para ser claro y conciso para una IA conversacional.


🐻 Zustand Cheatsheet Completo 🐻

Zustand es una librería de gestión de estados pequeña y rápida para React y JavaScript/TypeScript. Se basa en una API sencilla con hooks y evita el boilerplate, las inyecciones de proveedores (Provider) y el contexto complejo, lo que la hace muy fácil de aprender y usar.


1. 🌟 Conceptos Clave


2. 🛠️ Configuración Inicial

  1. Instalación:
    npm install zustand
    # o
    yarn add zustand
    # o
    pnpm add zustand
  2. Importación Básica:
    import { create } from 'zustand';

3. 🚀 Creación de un Store

Un store de Zustand es simplemente una función que devuelve un objeto con el estado inicial y las funciones para modificarlo.

// src/stores/bearStore.js
import { create } from 'zustand';

// 'create' recibe una función que tiene 'set' (para modificar estado) y 'get' (para leer estado)
const useBearStore = create((set, get) => ({
  // 1. Estado inicial
  bears: 0,
  fish: 0,
  location: 'forest',

  // 2. Acciones (funciones para modificar el estado)
  increasePopulation: () => set((state) => ({ bears: state.bears + 1 })), // Incrementa 'bears'
  removeAllBears: () => set({ bears: 0 }), // Establece 'bears' a 0
  addFish: (amount) => set((state) => ({ fish: state.fish + amount })),
  // Ejemplo de acción que usa 'get' para leer el estado actual
  resetAll: () => {
    // get() permite acceder al estado actual
    const currentBears = get().bears;
    console.log(`Reseteando ${currentBears} osos.`);
    set({ bears: 0, fish: 0, location: 'forest' });
  },
}));

export default useBearStore;

4. 🧰 Acceder y Modificar el Estado en Componentes React

Utiliza el hook generado por tu store (useBearStore en este ejemplo) para acceder al estado y las acciones.

import React from 'react';
import useBearStore from '../stores/bearStore'; // Importa tu store

function BearCounter() {
  // 1. Acceder a un valor específico del estado
  const bears = useBearStore((state) => state.bears); // Este componente solo se re-renderiza si 'bears' cambia

  // 2. Acceder a una acción
  const increasePopulation = useBearStore((state) => state.increasePopulation);
  const removeAllBears = useBearStore((state) => state.removeAllBears);
  const resetAll = useBearStore((state) => state.resetAll);

  return (
    <div>
      <h2>Contador de Osos: {bears}</h2>
      <button onClick={increasePopulation}>Añadir Oso</button>
      <button onClick={removeAllBears}>Remover Todos los Osos</button>
      <button onClick={resetAll}>Resetear Todo</button>
    </div>
  );
}

function FishCounter() {
  // 3. Acceder a múltiples partes del estado o acciones
  const fish = useBearStore((state) =&gt; state.fish);
  const addFish = useBearStore((state) =&gt; state.addFish);

  return (
    <div>
      <h3>Contador de Peces: {fish}</h3>
      <button onClick={() =&gt; addFish(1)}>Añadir Pez</button>
      <button onClick={() =&gt; addFish(5)}>Añadir 5 Peces</button>
    </div>
  );
}

// Ejemplo de componente Padre
function App() {
  return (
    <div>
      <h1>Aplicación de Gestión de Osos</h1>
      <BearCounter />
      <FishCounter />
    </div>
  );
}

export default App;

5. 🚀 Lógica Asíncrona

Maneja llamadas a APIs o cualquier operación asíncrona directamente dentro de las acciones del store.

// src/stores/userStore.js
import { create } from 'zustand';

const useUserStore = create((set) =&gt; ({
  user: null,
  isLoading: false,
  error: null,

  fetchUser: async (userId) =&gt; {
    set({ isLoading: true, error: null }); // Establece estado de carga

    try {
      const response = await fetch(`https://jsonplaceholder.typicode.com/users/${userId}`);
      if (!response.ok) {
        throw new Error('Error al obtener usuario');
      }
      const data = await response.json();
      set({ user: data, isLoading: false }); // Actualiza el estado con los datos
    } catch (err) {
      set({ error: err.message, isLoading: false, user: null }); // Maneja el error
    }
  },
}));

export default useUserStore;

Uso en Componente:

import React, { useEffect } from 'react';
import useUserStore from '../stores/userStore';

function UserProfile({ userId }) {
  const { user, isLoading, error, fetchUser } = useUserStore((state) =&gt; ({
    user: state.user,
    isLoading: state.isLoading,
    error: state.error,
    fetchUser: state.fetchUser,
  }));

  useEffect(() =&gt; {
    fetchUser(userId); // Dispara la acción asíncrona al montar o cambiar userId
  }, [userId, fetchUser]);

  if (isLoading) return <div>Cargando perfil...</div>;
  if (error) return <div>Error: {error}</div>;
  if (!user) return <div>No se encontró usuario.</div>;

  return (
    <div>
      <h3>Perfil de {user.name}</h3>
      <p>Email: {user.email}</p>
      <p>Teléfono: {user.phone}</p>
    </div>
  );
}

export default UserProfile;

6. 🔍 Selectores (Optimización de Re-renders)

Para evitar re-renders innecesarios, selecciona solo las partes del estado que tu componente realmente necesita.


7. 💾 Persistencia de Estado (Middleware persist)

Para almacenar el estado en localStorage, sessionStorage o cualquier otro almacenamiento.

// src/stores/persistedStore.js
import { create } from 'zustand';
import { persist } from 'zustand/middleware'; // Importa el middleware

const usePersistedStore = create(
  persist(
    (set, get) =&gt; ({
      count: 0,
      lastUpdated: Date.now(),
      increment: () =&gt; set((state) =&gt; ({ count: state.count + 1, lastUpdated: Date.now() })),
      reset: () =&gt; set({ count: 0, lastUpdated: Date.now() }),
    }),
    {
      name: 'my-app-storage', // Nombre clave en el almacenamiento local
      getStorage: () =&gt; localStorage, // O sessionStorage, o un almacenamiento personalizado
      // opcional: partialize: (state) =&gt; Object.fromEntries(Object.entries(state).filter(([key]) =&gt; !['nonPersistedKey'].includes(key))), // Guardar solo ciertas partes
      // opcional: blacklist: ['nonPersistedKey'], // No guardar estas claves
      // opcional: whitelist: ['persistedKey'], // Solo guardar estas claves
      // opcional: version: 1, // Para migraciones de esquema
    }
  )
);

export default usePersistedStore;

Uso: Funciona igual que cualquier otro store de Zustand.


8. 🧰 Middlewares Comunes

Zustand soporta middlewares para extender la funcionalidad del store. Se aplican envolviendo la función create o el persist middleware.


9. 💡 Buenas Prácticas y Consejos


Este cheatsheet te proporciona una referencia completa de Zustand, cubriendo sus conceptos esenciales, cómo crear y usar stores, manejar lógica asíncrona, optimizar re-renders, persistir el estado y aplicar middlewares, junto con las mejores prácticas para construir aplicaciones React eficientes y fáciles de mantener.