Profile Software Services

State management en frontend: Redux, Zustand o Context API

Gestionar el estado en aplicaciones React modernas o el state management puede ser un desafío, especialmente cuando la app crece y los datos se comparten entre muchos componentes. En este artículo, vamos a explicar cuáles son los conceptos clave de la gestión de estado y luego analizaremos tres soluciones populares: Redux, Zustand y Context API, explorando sus arquitecturas, patrones de diseño y casos de uso recomendados. 

El objetivo será explicar no sólo con ejemplos de casos, si no también dar una idea de lo qué está pasando detrás de cada librería y cómo usarla correctamente

Conceptos clave de gestión de estado 

Antes de entrar en las librerías, es importante entender los elementos:

Estado (State) 

El estado es toda la información que define la apariencia y el comportamiento de la aplicación en un momento dado. Por ejemplo, un contador, un tema de color o la lista de productos en un carrito

type CounterState = { count: number }; 
const state: CounterState = { count: 0 }; 

Acción (Action)

Una acción es un objeto que describe qué cambio queremos hacer en el estado. En Redux, por ejemplo:

interface IncrementAction { 
 type: 'counter/increment'; 
 payload: { amount: number }; 
} 

const incrementAction: IncrementAction = { type: 'counter/increment', payload: { amount: 5 } }; 

Piénsalo como un mensaje que le dice a tu app qué hacer, pero no lo hace directamente.

Reducer 

Un reducer es una función pura que recibe el estado actual y una acción, y devuelve un nuevo estado. Nunca modifica el estado original. 

function counterReducer(state: CounterState = { count: 0 }, action: IncrementAction): CounterState { 
 switch(action.type) { 
 case 'counter/increment': 
 return { count: state.count + action.payload.amount }; 
 default: 
 return state; 
 } 
} 

Analogía: el reducer es un juez imparcial que decide cómo cambia el estado según la acción recibida.

Store 

El store es el contenedor central del estado. En Redux es único; en Zustand puedes tener varios si quieres separar responsabilidades.

import { configureStore } from '@reduxjs/toolkit'; 
const store = configureStore({ reducer: counterReducer }); 

Provider 

En Context API, un Provider es un componente que proporciona el estado a todos los componentes hijos que lo necesiten. 

import React, { createContext, useContext } from 'react'; 
const ThemeContext = createContext<string>('light'); 
<ThemeContext.Provider value="dark"> 
 <App /> 
</ThemeContext.Provider>; 

Selector 

Un selector es una función que elige solo la parte del estado que necesita un componente, evitando renders innecesarios.

const count = useStore((state: CounterState) => state.count);

Redux: Arquitectura Flux y Predictibilidad

Fundamentos Arquitectónicos 

Redux se basa en Flux, con un flujo de datos unidireccional

Principios clave: 

  1. Una única fuente de verdad: un solo store. 
  2. Estado de solo lectura: cambios solo mediante acciones. 
  3. Reducers puros: devuelven un nuevo estado sin modificar el original.
import { configureStore, createSlice, PayloadAction } from '@reduxjs/toolkit'; 
interface CounterState { count: number; } 
const counterSlice = createSlice({ 
 name: 'counter', 
 initialState: { count: 0 } as CounterState, 
 reducers: { 
 increment: (state, action: PayloadAction<number>) => { state.count += action.payload; }, 
 }, 
}); 
const store = configureStore({ reducer: counterSlice.reducer }); 

Patrones de Diseño 

Características Distintivas 

Características Distintivas Redux

Context API: Solución Nativa de React

Fundamentos Arquitectónicos 

Context API permite compartir datos sin prop drilling. Se basa en la composición de React y proporciona Providers y Consumers.

const ThemeContext = createContext<'light' | 'dark'>('light');
function App() {
const theme = useContext(ThemeContext);
return <div className={theme}>Hola mundo</div>;
}

Patrones de Diseño

Características Distintivas

Zustand: Minimalismo y Pragmatismo

Fundamentos Arquitectónicos

Zustand ofrece hooks para manejar el estado de manera simple y eficiente.

import create from 'zustand';
interface CounterState { count: number; increment: () => void; } 
const useStore = create<CounterState>((set) => ({ 
 count: 0, 
 increment: () => set((state) => ({ count: state.count + 1 })), })); 
function Counter() { 
 const count = useStore((state) => state.count); 
 const increment = useStore((state) => state.increment); 
 return <button onClick={increment}>{count}</button>; 
} 

 Patrones de Diseño 

Características Distintivas 

Análisis Comparativo

Consideraciones de Rendimiento 

Casos de Uso Recomendados 

Patrones Arquitectónicos Transversales

Inmutabilidad 

Separación de Responsabilidades 

Testabilidad 

Conclusiones 

No hay una solución perfecta. La elección depende del tamaño de la app, equipo y necesidades de rendimiento

La tendencia apunta a soluciones ligeras como Zustand, priorizando la developer experience sin sacrificar capacidad técnica, aunque Redux sigue siendo relevante en entornos empresariales. 

 Si te interesa estar al día en desarrollo web, arquitectura y buenas prácticas en programación, síguenos en nuestras redes sociales y Canal de YouTube.

Referencias 

Salir de la versión móvil