Lección 11 de 20 · Lectura y práctica
Implementar Zustand para estado global optimizado
Concepto claveZustand es una biblioteca de gestión de estado global minimalista para React que resuelve problemas de escalabilidad y complejidad que aparecen en aplicaciones Expo avanzadas. A diferencia de Redux, que requiere.
Del concepto a la práctica
Taller de esta lección
Zustand resulta adecuado cuando varias pantallas necesitan el mismo estado de interfaz, como el filtro seleccionado o el identificador de una tarea activa. La optimización depende de suscribirse al fragmento necesario, no de convertir todos los datos en globales.
Ejemplo resuelto
El store contiene filter:"pending" y selectedTaskId:null, además de setFilter y selectTask. Una lista se suscribe solo a filter; un panel de detalle solo a selectedTaskId. Con selectores que devuelven primitivas estables, seleccionar una tarea no notifica a la suscripción exclusiva de filter. Un render del componente padre o props distintas aún podría renderizar la lista: no prometas ausencia absoluta de renders sin medirla.
Pruébalo
Separa preferencias de datos remotos.
Define dos selecciones pequeñas en lugar de devolver el store completo.
Registra qué componente se actualiza al cambiar cada campo.
Restablece el store al cerrar sesión o cambiar de espacio.
Error frecuente: guardar en Zustand la respuesta completa de una consulta remota y duplicar su caché. Corrígelo dejando los datos del servidor en su gestor de consultas y usando Zustand para filtros o preferencias.
Comprueba tu resultado
El registro debe mostrar que cambiar filter actualiza la lista, cambiar selectedTaskId actualiza el detalle y ninguna acción modifica el campo no relacionado.

Mapa de prácticaUna condición decide qué camino ejecuta el programa. Un bucle repite una operación mientras queden elementos, y termina cuando la lista se agota. Separar ambas ideas ayuda a seguir el flujo y comprobar casos límite.
Ver la infografía en tamaño completo ↗Concepto clave
Zustand es una biblioteca de gestión de estado global minimalista para React que resuelve problemas de escalabilidad y complejidad que aparecen en aplicaciones Expo avanzadas. A diferencia de Redux, que requiere boilerplate significativo con acciones, reducers y middlewares, Zustand utiliza un enfoque basado en hooks que es más intuitivo y menos verboso.
Imagina que estás construyendo una aplicación de comercio electrónico con Expo. En lugar de tener que pasar props manualmente a través de múltiples componentes (prop drilling) o configurar un sistema complejo de contexto, Zustand te permite crear un store centralizado que cualquier componente puede acceder directamente. Es como tener una caja fuerte compartida en una oficina: todos los empleados (componentes) saben dónde está y pueden acceder a lo que necesitan sin tener que pedir permiso a través de una cadena de mando.
La verdadera ventaja de Zustand en aplicaciones Expo avanzadas es su optimización automática. Cuando un componente se suscribe a solo una parte del estado, solo se rerenderiza cuando esa parte específica cambia. Esto es crucial para aplicaciones móviles donde el rendimiento afecta directamente la experiencia del usuario y el consumo de batería.
Cómo funciona en la práctica
Implementar Zustand en una aplicación Expo sigue un flujo claro. Primero, instalas la biblioteca: npm install zustand o yarn add zustand. Luego, creas tu store definiendo el estado inicial y las acciones que lo modifican.
Veamos el proceso paso a paso:
- Crear un archivo store.js donde defines tu estado global
- Usar la función create de Zustand para generar tu store
- Definir el estado inicial y las funciones que lo modifican (set)
- En tus componentes, importar el hook personalizado generado
- Seleccionar solo las partes del estado que cada componente necesita
La magia está en cómo Zustand maneja las suscripciones. Cuando usas el hook en un componente, automáticamente se suscribe a los cambios del estado, pero solo se rerenderiza si las propiedades específicas que seleccionaste han cambiado. Esto elimina renders innecesarios que son comunes en soluciones de contexto nativo de React.
Codigo en accion
Veamos un ejemplo real de una aplicación de tareas con Expo. Primero, el enfoque tradicional con Context API:
// Antes: Context API complejo
export const TasksContext = React.createContext();
export function TasksProvider({ children }) {
const [tasks, setTasks] = useState([]);
const [filter, setFilter] = useState('all');
const addTask = (task) => {
setTasks([...tasks, task]);
};
const value = {
tasks,
filter,
addTask,
setFilter
};
return (
{children}
);
}
// En un componente hijo profundo:
function TaskList() {
const { tasks, filter } = useContext(TasksContext);
// Este componente se rerenderiza aunque solo cambie filter
return (
{tasks.filter(t => filter === 'all' || t.status === filter).map(task => (
))}
);
}Ahora, el mismo ejemplo optimizado con Zustand:
// Despues: Zustand optimizado
import create from 'zustand';
const useTaskStore = create((set) => ({
tasks: [],
filter: 'all',
addTask: (task) => set((state) => ({
tasks: [...state.tasks, task]
})),
setFilter: (filter) => set({ filter }),
clearCompleted: () => set((state) => ({
tasks: state.tasks.filter(t => !t.completed)
}))
}));
// En el mismo componente hijo:
function TaskList() {
// Solo se suscribe a tasks y filter, no a todo el store
const tasks = useTaskStore((state) => state.tasks);
const filter = useTaskStore((state) => state.filter);
// Solo se rerenderiza si tasks o filter cambian
const filteredTasks = tasks.filter(t =>
filter === 'all' || t.status === filter
);
return (
{filteredTasks.map(task => (
))}
);
}Errores comunes
Al implementar Zustand en aplicaciones Expo, estos son los errores más frecuentes:
- Suscribirse a todo el store: Usar
useTaskStore()sin selector hace que el componente se rerenderice con cualquier cambio en el store. Siempre usa selectores específicos:useTaskStore(state => state.tasks). - Mutación directa del estado: En Zustand, nunca modifiques el estado directamente. Siempre usa la función
setproporcionada. Mal:state.tasks.push(newTask). Bien:set(state => ({tasks: [...state.tasks, newTask]})). - Olvidar la optimización de selectores: Para selectores complejos que realizan cálculos costosos, usa
useMemoo la funciónshallowde Zustand para evitar recálculos en cada render. - Store demasiado grande: Agrupar todo el estado de la aplicación en un solo store puede volverse inmanejable. Divide stores lógicamente por dominio (authStore, cartStore, userStore).
- No manejar estado asíncrono correctamente: Para operaciones async, usa patrones claros. Zustand no prescribe cómo manejar async, pero un patrón común es tener estados de loading/error separados.
Checklist de dominio
Para verificar que dominas Zustand en aplicaciones Expo, asegúrate de poder:
- Crear un store con estado inicial y acciones de modificación usando la función
create - Usar selectores específicos en componentes para optimizar rerenders
- Implementar correctamente actualizaciones de estado inmutables con la función
set - Dividir stores lógicamente cuando la aplicación escala (múltiples stores)
- Manejar estado asíncrono con patrones claros (loading, error, data)
- Integrar Zustand con otras bibliotecas como React Navigation para estado de navegación
- Usar middleware de Zustand para logging, persistencia o devtools en desarrollo
Refactorizar una aplicación Expo de comercio electrónico de Context API a Zustand
En este ejercicio práctico, refactorizarás una aplicación Expo existente que usa Context API para gestión de estado a usar Zustand optimizado.
- Contexto inicial: Descarga o clona la aplicación base que tiene:
- Un carrito de compras con Context API
- Estado de usuario (autenticación) con Context separado
- Componentes que sufren de prop drilling y rerenders innecesarios
- Paso 1: Instalación y setup
- Instala Zustand en el proyecto:
npm install zustand - Crea una carpeta
stores/en la raíz del proyecto
- Instala Zustand en el proyecto:
- Paso 2: Crear el store del carrito
- Crea
stores/cartStore.js - Define el estado inicial: items (array), total (number)
- Implementa acciones: addItem, removeItem, clearCart, updateQuantity
- Asegúrate que todas las acciones usen el patrón inmutable
- Crea
- Paso 3: Crear el store de autenticación
- Crea
stores/authStore.js - Estado: user (object/null), isLoading (boolean), error (string/null)
- Acciones: login (async), logout, clearError
- Implementa manejo adecuado de estados loading/error
- Crea
- Paso 4: Refactorizar componentes
- Reemplaza todos los
useContextpor hooks de Zustand - En cada componente, usa selectores específicos (no todo el store)
- Para el componente CartSummary, solo suscríbete a
total - Para ProductList, solo suscríbete a
itemspara mostrar cantidad en carrito
- Reemplaza todos los
- Paso 5: Optimización avanzada
- En componentes con cálculos costosos (como filtrado de productos), usa
useMemo - Implementa persistencia básica para el carrito usando localStorage (AsyncStorage en Expo)
- Agrega logging en desarrollo con middleware de Zustand
- En componentes con cálculos costosos (como filtrado de productos), usa
- Entrega: Proporciona:
- Los archivos de store completos
- 2-3 componentes refactorizados mostrando el antes/después
- Métricas de rendimiento (menor cantidad de rerenders)
Pistas
- Recuerda que en Zustand, el estado debe ser siempre inmutable. Usa el operador spread o métodos que retornen nuevos arrays/objects.
- Para selectores que combinan múltiples valores del store, considera crear un hook personalizado que use useMemo internamente para optimización.
- Cuando dividas en múltiples stores, algunos componentes necesitarán acceder a ambos. Puedes crear hooks combinados o simplemente usar múltiples useStore hooks.
Evalua tu comprension
Completa el quiz interactivo de arriba para ganar XP.
Sigue con Desarrollo Avanzado de Aplicaciones con Expo: De Concepto a Producción
Esta lección forma parte de un curso de Cursalo. Revisa su programa y elige entre la compra individual o el acceso a toda la escuela.
Si ya tenías acceso a este curso, entra con tu cuenta: tus derechos y tu progreso se conservan. No necesitas comprarlo de nuevo.