Marcio Cunha

Cómo gestionar estado global en React con Zustand sin rodeos

Aprende a manejar el estado global en React de forma limpia, rápida y sin código repetitivo usando Zustand en lugar de Redux.

Marcio Cunha•6 min
También disponible en:EnglishPortuguês
Resumen
  • Zustand elimina la verbosidad clásica de reducers y actions al adoptar una API basada en hooks puros
  • La selectividad de estado integrada evita renderizados innecesarios en componentes que no han cambiado
  • Gestionar datos fuera del ecosistema de componentes de React facilita las pruebas unitarias y la lógica asíncrona
  • La optimización de paquetes web, como se detalla al aplicar code splitting en React, mejora la entrega general de la app
  • El enfoque minimalista reemplaza herramientas complejas sin sacrificar la escalabilidad en aplicaciones grandes

El desafío de compartir datos entre componentes en React

Cuando construimos aplicaciones web modernas, pronto nos damos cuenta de que no toda información pertenece a un solo rincón de la pantalla. El usuario inicia sesión, cambia el tema de la interfaz o añade un artículo al carrito de compras, y estos datos deben aparecer al instante en varios lugares distintos. En la práctica, gestionar este ecosistema exige compartir información globalmente sin convertir el código en un enredo imposible de mantener. Aquí es donde surge el famoso estado global, un almacén central donde guardamos todo lo que diversas partes del sistema necesitan ver y modificar.

Históricamente, la comunidad recurrió a herramientas robustas como Redux para resolver esta ecuación. Aunque extremadamente potente, Redux exige una cantidad masiva de código repetitivo, conocido como boilerplate. Para crear un simple cambio de datos, tenías que configurar actions, reducers, types y middlewares complejos antes de ver cualquier cosa funcionando en pantalla. Para equipos más pequeños o proyectos que buscan agilidad, esta burocracia penaliza la productividad y hace que la curva de aprendizaje sea innecesariamente empinada. Como vimos al debatir ¿bundle pesado en React? Cómo aplicar code splitting eficiente, mantener el código limpio impacta directamente en el rendimiento y la mantenibilidad.

Conoce Zustand y su enfoque minimalista

Zustand llega como un soplo de aire fresco en este escenario. En alemán, el nombre significa literalmente estado. Se trata de una biblioteca minimalista creada por los mismos desarrolladores detrás de Zustand y Jotai, enfocada en entregar el máximo poder con el mínimo código posible. Utiliza ganchos nativos de React de manera directa, descartando proveedores complejos de contexto en la raíz de la aplicación y eliminando por completo la necesidad de reducers rígidos.

En la práctica, esto significa que crear una central de datos global se reduce a escribir pocas líneas de JavaScript moderno. Defines una función que almacena tanto las variables como las funciones responsables de modificarlas, y cualquier componente puede consumir esos datos al instante. No hay secretos arquitectónicos profundos ni conceptos abstractos que memorizar el primer día de uso. Esta simplicidad hace que desarrolladores novatos y séniors alcancen el mismo nivel de eficiencia en pocos minutos de lectura.

Creando tu primer almacén de datos sin esfuerzo

Para entender cómo funciona la herramienta en el banco de trabajo, vamos a construir un ejemplo práctico de gestión de un carrito de compras sencillo. El primer paso consiste en instalar la biblioteca en tu proyecto utilizando el gestor de paquetes de tu preferencia, como npm o yarn, asegurando que el entorno esté listo para recibir la nueva dependencia.

A continuación, creamos un archivo dedicado para nuestro almacenamiento, que llamaremos store. Es dentro de él donde definimos la estructura de los datos y las acciones permitidas. Observa lo directa y limpia que es la sintaxis, muy similar a la creación de un hook personalizado común:

import { create } from 'zustand';

export const useCartStore = create((set) => ({
  items: [],
  addItem: (item) => set((state) => ({ items: [...state.items, item] })),
  removeItem: (id) => set((state) => ({
    items: state.items.filter((item) => item.id !== id),
  })),
}));

Con pocas líneas, estructuramos la base completa de datos. La función set sirve precisamente para actualizar el estado de manera inmutable, asegurando que React note el cambio y actualice la interfaz visual. No hay switch-cases gigantescos ni archivos repartidos por carpetas distantes.

Consumiendo el estado directamente en los componentes

La verdadera belleza de Zustand aparece en el momento en que consumimos esta información dentro de los componentes visuales. Como la biblioteca se integra de forma nativa con los hooks de React, no necesitas envolver toda tu aplicación en voluminosos componentes proveedores. Basta con importar el hook creado y extraer exactamente la porción de información que tu componente necesita para renderizarse en pantalla.

Este enfoque aporta un aumento colosal de rendimiento. En soluciones tradicionales de estado global, cualquier pequeño cambio en una variable remota podía disparar la re-renderización de componentes enteros que ni siquiera estaban usando ese dato específico. Con Zustand, el componente se suscribe únicamente a la porción de estado que le interesa, evitando desperdiciar procesamiento en el navegador del usuario.

import React from 'react';
import { useCartStore } from './cartStore';

export function CartCounter() {
  const items = useCartStore((state) => state.items);
  
  return (
    <div className='p-4 bg-gray-100 rounded'>
      <p>Artículos en el carrito: {items.length}</p>
    </div>
  );
}

En el ejemplo anterior, el componente CartCounter observa exclusivamente la lista de artículos. Si otra parte de la aplicación modifica el tema visual o el perfil del usuario, este componente permanecerá intacto, ahorrando ciclos preciosos de renderizado y manteniendo la interfaz sumamente fluida y receptiva.

Manejando solicitudes asíncronas y APIs

Las aplicaciones reales necesitan comunicarse con servidores externos para buscar datos, autenticar usuarios y guardar información en bases de datos. Una de las grandes ventajas de Zustand es que gestiona operaciones asíncronas de forma totalmente natural, sin exigir la instalación de middlewares adicionales como Redux Thunk o Redux Saga. Como las acciones del almacén son simplemente funciones JavaScript comunes, puedes usar async/await sin ninguna barrera.

Para buscar datos de una API, basta con declarar una función asíncrona dentro de tu store y actualizar el estado tan pronto como llegue la respuesta. Esto simplifica drásticamente la arquitectura de comunicación con el backend, permitiendo que la lógica de negocio permanezca concentrada justo donde residen los datos, facilitando las pruebas automatizadas y la depuración de errores en producción.

export const useUserStore = create((set) => ({
  user: null,
  loading: false,
  fetchUser: async (id) => {
    set({ loading: true });
    const response = await fetch(`https://api.ejemplo.com/users/${id}`);
    const data = await response.json();
    set({ user: data, loading: false });
  },
}));

De este modo, el flujo de datos asíncronos se vuelve transparente y directo al grano. Cualquier pantalla de la aplicación puede disparar la función de búsqueda simplemente llamando al hook y consumiendo el indicador de carga o los datos de usuario ya formateados. Para complementar esta implementación en entornos de producción, consulte también nuestros análisis técnicos sobre Cómo usar embeddings locales con ChromaDB en búsqueda semántica y Cómo gestionar concurrencia en Rust con Tokio y Channels.

Reflexiones finales sobre arquitectura frontend

Adoptar una herramienta minimalista cambia la forma en que abordamos el desarrollo de aplicaciones web complejas. Al eliminar capas excesivas de abstracción y enfocarnos en lo que realmente importa —la legibilidad del código y el rendimiento de la interfaz— ganamos velocidad de entrega y reducimos la deuda técnica a largo plazo. Zustand demuestra que no necesitamos frameworks complejos para resolver problemas cotidianos de estado global.

Evaluando el panorama actual del ecosistema React, las herramientas ligeras enfocadas en la experiencia del desarrollador llegaron para quedarse. Reemplazar patrones heredados y pesados por alternativas ágiles permite que los equipos se concentren en la experiencia real del usuario final. Elegir la tecnología adecuada para gestionar tus datos asegura que la aplicación siga siendo escalable, limpia y fácil de mantener a medida que el proyecto crece con los años.