logoImagina
iconCurso
Te recomendamos nuestro curso de React 19
Descubre el curso de React 19
Ir al curso

¿Qué es y Cómo usar Redux en React?

iconImage
Escrito por Equipo de Imagina
Actualizado el 09-08-2024
Duración: 10 min

Cuando desarrollamos aplicaciones complejas con React, gestionar el estado se convierte en un desafío. Redux emerge como una solución poderosa para manejar el estado de manera predecible y eficiente en aplicaciones de gran escala. En este artículo, exploraremos qué es Redux, por qué es tan crucial en el desarrollo de aplicaciones con React y cómo podemos implementarlo eficazmente. Nos adentraremos en los conceptos fundamentales, desde la creación de un store hasta la definición de reducers y la gestión del estado global.

Joven programador utilizando Redux en React

¿Qué es Redux?

Redux es una biblioteca de JavaScript para el manejo del estado de aplicaciones complejas. Originalmente diseñada para aplicaciones de una sola página, ha ganado popularidad debido a su arquitectura predecible, lo cual facilita el mantenimiento y escalabilidad de aplicaciones de gran tamaño.

Redux funciona utilizando un principio clave: el estado global de la aplicación se almacena en un único árbol de estado, conocido como 'store'. Este paradigma unificado simplifica la tarea de depurar y rastrear cambios de estado en la aplicación.

En lugar de propagar el estado de un componente a otro a través de props, Redux permite acceder al estado global directamente, garantizando que cada componente tenga acceso a información relevante sin necesidad de prop drilling.

No obstante, es importante mencionar que, aunque Redux es una herramienta poderosa, su uso no siempre es necesario. Para aplicaciones pequeñas o medianas, la complejidad añadida puede no justificar los beneficios.

Principales Características de Redux

Uno de los aspectos más destacados de Redux es su arquitectura unidireccional. Esto significa que el flujo de datos sigue un camino claro y predecible: las acciones disparan actualizaciones del estado a través de los reducers, que luego actualizan la store.

Otra característica central es su enfoque en la inmutabilidad. En Redux, el estado no se modifica directamente. En su lugar, se crean nuevos objetos de estado mediante funciones puras (reducers). Este enfoque asegura cambios predecibles y facilita el positracking de cada actualización del estado.

Redux también proporciona un potente middleware que permite interceptar acciones y realizar tareas asíncronas antes de llegar a los reducers. Middleware como Thunk y Saga son comúnmente utilizados para manejar operaciones como llamadas a APIs.

Finalmente, Redux es compatible con cualquier framework o biblioteca de interfaz. Aunque es comúnmente utilizado con React, su agnosticismo en cuanto a la interfaz lo hace adecuado para aplicaciones construidas con Angular, Vue o incluso Vanilla JS.

¿Por qué Usar Redux?

El uso de Redux es altamente beneficioso cuando se trata de manejar aplicaciones con múltiples estados compartidos entre varios componentes. Esto es especialmente cierto en aplicaciones grandes donde el seguimiento del estado compartido se vuelve una tarea compleja.

Redux mejora la legibilidad y mantenibilidad del código. La arquitectura unidireccional de Redux y el manejo centralizado del estado facilitan la tarea de debugar problemas. Con Redux DevTools, es posible rastrear y revertir cada cambio de estado, lo cual es invaluable durante el proceso de desarrollo.

Otro beneficio clave es la capacidad de gestionar side effects de manera más controlada. Con middleware como Redux Thunk o Saga, las tareas asíncronas se integran de manera fluida, reduciendo la complejidad del manejo de funciones asíncronas dispersas en múltiples partes del código.

Además, Redux fomenta la práctica de escribir funciones puras y predecibles (reducers). Esto, combinado con pruebas unitarias, produce código más robusto y menos propenso a errores.

Cómo Integrar Redux con React

Configuración Inicial del Proyecto

Para integrar Redux con React, primero debemos configurar un proyecto de React. Podemos comenzar utilizando Create React App, una herramienta que nos facilita la creación de un entorno de desarrollo React con configuraciones preestablecidas.

1npx create-react-app mi-proyecto-redux

Una vez que nuestro proyecto esté configurado, navegamos a su directorio:

1cd mi-proyecto-redux

Ahora estamos listos para añadir las dependencias necesarias para Redux y su integración con React.

Instalación de Dependencias Necesarias

Para instalar las bibliotecas necesarias, ejecutaremos el siguiente comando, el cual instalará Redux y React-Redux:

1npm install redux react-redux

Redux es la biblioteca que nos permitirá manejar el estado global de nuestra aplicación, mientras que React-Redux proporciona los enlaces necesarios para conectar Redux con los componentes de React.

Este último paquete incluye utilities como Provider y connect, que son esenciales para la integración efectiva entre React y Redux.

Configuración de Store de Redux

La configuración del store de Redux es el siguiente paso crítico. Para ello, creamos un nuevo archivo, típico en un directorio llamado src/store.js, con el siguiente contenido:

1import { createStore } from 'redux'; 2import rootReducer from './reducers'; 3 4const store = createStore(rootReducer); 5 6export default store;

El createStore es una función de Redux que crea el store utilizando un reducer (en este ejemplo, el rootReducer). A continuación, vinculamos el store con nuestra aplicación React. En el archivo src/index.js, importamos Provider y el store de Redux:

1import React from 'react'; 2import ReactDOM from 'react-dom'; 3import { Provider } from 'react-redux'; 4import store from './store'; 5import App from './App'; 6 7ReactDOM.render( 8 <Provider store={store}> 9 <App /> 10 </Provider>, 11 document.getElementById('root') 12);

El Provider de React-Redux envuelve nuestra aplicación principal, asegurando que todos los componentes descendientes tengan acceso al store.

Conceptos Clave de Redux

Action

En Redux, un action es una función pura que envía datos desde nuestra aplicación al store de Redux. Dichos datos son la única fuente de información para el store. Es importante recordar que las acciones deben ser objetos con una propiedad type que describe el tipo de acción que está ocurriendo, y, opcionalmente, otras propiedades que lleven la información necesaria.

A continuación se muestra un ejemplo de una acción:

1const increment = () => { 2 return { 3 type: 'INCREMENT' 4 }; 5};

En este ejemplo, la función increment es una acción que tiene un type de 'INCREMENT'. Este type será utilizado más adelante por los reducers para saber qué tipo de actualización realizar en el estado global.

Acciones con Datos

Las acciones no siempre son simples; a veces necesitan llevar datos adicionales. Aquí hay un ejemplo de una acción que lleva una carga útil (payload):

1const addTodo = (text) => { 2 return { 3 type: 'ADD_TODO', 4 payload: text 5 }; 6};

En este ejemplo, la acción addTodo lleva un payload que contiene el texto del nuevo todo. Estas acciones más complejas son comunes y permiten una gestión avanzada del estado en nuestras aplicaciones.

Reducer

En Redux, un reducer es una función pura que recibe el estado actual y una acción, y retorna un nuevo estado. Los reducers especifican cómo cambia el estado de la aplicación en respuesta a una acción enviada al store.

El reducer debe ser puro, lo que significa que no debe tener efectos secundarios y siempre debe retornar el mismo resultado dado el mismo conjunto de entradas. Aquí tienes un ejemplo de un reducer sencillo:

1const initialState = { count: 0 }; 2 3const counterReducer = (state = initialState, action) => { 4 switch (action.type) { 5 case 'INCREMENT': 6 return { 7 ...state, 8 count: state.count + 1 9 }; 10 case 'DECREMENT': 11 return { 12 ...state, 13 count: state.count - 1 14 }; 15 default: 16 return state; 17 } 18}; 19 20export default counterReducer;

En este ejemplo, counterReducer gestiona el estado para un contador simple. Dependiendo del type de la acción emitida (INCREMENT o DECREMENT), el estado se actualizará correspondientemente.

Combinación de Reducers

En aplicaciones más grandes, es común tener múltiples reducers, cada uno gestionando diferentes partes del estado. Redux nos permite combinar estos reducers en uno solo utilizando la función combineReducers.

1import { combineReducers } from 'redux'; 2import counterReducer from './counterReducer'; 3import anotherReducer from './anotherReducer'; 4 5const rootReducer = combineReducers({ 6 counter: counterReducer, 7 anotherPart: anotherReducer 8}); 9 10export default rootReducer;

Esto permite una gestión modular y escalable del estado, ya que cada reducer se encarga de una parte específica del estado global.

Descubre la formación a tu medida
Rellena el formulario para obtener más información sobre los cursos.
Tamaño de la empresa *
Términos y condiciones *

Store de Redux

El store es el corazón de una aplicación Redux. Es un objeto que trae consigo el estado de nuestra aplicación y un conjunto de funciones para gestionar dicho estado. El store es creado usando la función createStore de Redux y necesita un reducer como argumento.

Primero, importamos createStore y nuestro rootReducer:

1import { createStore } from 'redux'; 2import rootReducer from './reducers';

Entonces, creamos el store:

1const store = createStore(rootReducer);

Ahora, el store está configurado para manejar el estado de nuestra aplicación utilizando el rootReducer.

Funciones del Store en Redux

El store tiene varias funciones importantes:

  • getState(): Recupera el estado actual.
  • dispatch(action): Envía una acción para actualizar el estado.
  • subscribe(listener): Añade un listener que se ejecuta cada vez que el estado cambia.
1// Obtener el estado actual 2const currentState = store.getState(); 3 4// Enviar una acción 5store.dispatch({ type: 'INCREMENT' }); 6 7// Suscribirse a los cambios en el estado 8store.subscribe(() => { 9 console.log(store.getState()); 10});

Estas funciones permiten a los desarrolladores interactuar con el estado global de manera controlada y predecible, asegurando una gestión eficiente del estado en la aplicación.

Herramientas y extensiones útiles

Redux DevTools

Redux DevTools es una de las herramientas más valiosas para los desarrolladores que trabajan con Redux. Esta extensión de navegador permite inspeccionar cada estado y acción en tiempo real, lo que facilita la depuración y el seguimiento de los cambios en el estado de la aplicación.

Con Redux DevTools, puedes viajar en el tiempo volviendo a estados anteriores, lo que es invaluable para probar y diagnosticar problemas sin tener que reiniciar la aplicación constantemente. Aquí está cómo integrar Redux DevTools con tu aplicación:

1import { createStore, applyMiddleware, compose } from 'redux'; 2import rootReducer from './reducers'; 3 4const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; 5const store = createStore( 6 rootReducer, 7 composeEnhancers(applyMiddleware(...middleware)) 8);

Esta configuración permite conectar la store de Redux con las DevTools.

Redux Toolkit

Redux Toolkit es el enfoque oficial recomendado para escribir lógica Redux. Simplifica la configuración de la store, la creación de reducers, la ejecución de efectos secundarios y más, utilizando buenas prácticas por defecto. Redux Toolkit ayuda a reducir la cantidad de código boilerplate que normalmente necesitas escribir para Redux y evita errores comunes. Por ejemplo, puedes crear una slice de estado con reducers y acciones utilizando createSlice:

1import { configureStore, createSlice } from '@reduxjs/toolkit'; 2 3const exampleSlice = createSlice({ 4 name: 'example', 5 initialState, 6 reducers: { 7 increment(state, action) { 8 state.value += action.payload; 9 }, 10 }, 11}); 12 13const store = configureStore({ 14 reducer: { 15 example: exampleSlice.reducer, 16 }, 17});

Este código muestra cómo createSlice automáticamente genera las acciones correspondientes a los reducers que definimos.

Otras bibliotecas complementarias

Además de las herramientas principales, existen otras bibliotecas que complementan a Redux y facilitan el trabajo con estados globales en aplicaciones complejas. Algunas de estas son:

  • Reselect: Permite crear selectores reutilizables y memoizados para optimizar la selección de partes del estado.
  • Redux Saga: Es un middleware que ayuda a manejar efectos secundarios en tus aplicaciones Redux de una forma más manejable, utilizando sagas.
  • Redux Thunk: Permite escribir creadores de acciones que devuelven una función en lugar de un objeto de acción, útil para manejar operaciones asíncronas.

Estas herramientas y extensiones proporcionan una poderosa suite de recursos que, cuando se utilizan juntas, ofrecen una solución robusta para el manejo de estado en aplicaciones modernas de React.

Mejores prácticas y patrones comunes

Organización del código

Una buena organización del código es fundamental para mantener aplicaciones Redux escalables y fáciles de mantener. Estructurar los archivos por características o rutas puede ayudar a localizar rápidamente el código relevante para cada parte de la aplicación. Además, es crucial separar la lógica de los reducers, las acciones y los selectores en diferentes archivos. Por ejemplo:

1// actions.js 2export const addItem = item => ({ 3 type: 'ADD_ITEM', 4 payload: item 5}); 6 7// reducers.js 8const initialState = { items: [] }; 9export default function itemsReducer(state = initialState, action) { 10 switch (action.type) { 11 case 'ADD_ITEM': 12 return {...state, items: [...state.items, action.payload]}; 13 default: 14 return state; 15 } 16}

Esto no solo mejora la legibilidad sino también facilita la reutilización y el testing.

Performance y optimización

La performance es un aspecto crítico en aplicaciones grandes. Utilizar técnicas como memorización de selectores con bibliotecas como Reselect puede ayudar a evitar cálculos innecesarios y mejorar la eficiencia de renderizado. Además, es importante limitar el número de actualizaciones de estado innecesarias y optimizar el uso de componentes conectados a Redux.

1import { createSelector } from 'reselect'; 2 3const selectItems = state => state.items; 4const selectItemCount = createSelector( 5 [selectItems], 6 items => items.length 7);

Testing de aplicaciones Redux

El testing es esencial para asegurar que las aplicaciones funcionen correctamente, especialmente al escalar. Los tests para aplicaciones Redux deben cubrir acciones, reducers y selectores. Utilizar herramientas como Jest para pruebas unitarias y Cypress para pruebas de integración puede facilitar este proceso. Aquí un ejemplo de cómo testear un reducer:

1import reducer, { addItem } from './reducers'; 2 3describe('itemsReducer', () => { 4 it('should handle ADD_ITEM', () => { 5 const initialState = { items: [] }; 6 const newItem = { name: 'Redux Toolkit' }; 7 const action = addItem(newItem); 8 const result = reducer(initialState, action); 9 expect(result.items).toContain(newItem); 10 }); 11});

Implementar estas prácticas y patrones no solo mejora la calidad y mantenibilidad de la aplicación, sino que también facilita la colaboración entre desarrolladores en proyectos complejos.

Conviertete en un experto de React

Redux es una biblioteca poderosa para gestionar el estado de las aplicaciones React. A través de este tutorial, has aprendido los conceptos fundamentales y cómo implementarlos en tu proyecto. Sin embargo, dominar Redux requiere práctica y una comprensión más profunda.

Si deseas llevar tus habilidades al siguiente nivel y convertirte en un experto en Redux, te invitamos a inscribirte en nuestro curso completo de React.

¡Inscríbete ahora y transforma tu manera de desarrollar aplicaciones con React!

Descubre la formación a tu medida
Rellena el formulario para obtener más información sobre los cursos.
Tamaño de la empresa *
Términos y condiciones *
Tutoriales relacionados
Pinia vs Vuex ¿Cuál es Mejor?
Explorando los fundamentos de Pinia y Vuex: Una guía detallada para entender que herramienta de gestión de estado se adapta mejor a tus proyectos de Vue 3
¿Qué es Vue JS y Para qué Sirve?
Aprende todo sobre Vue, el framework que combina simplicidad y eficacia, y descubre por qué es la elección predilecta para desarrolladores y empresas alrededor del mundo.
Cómo Crear Componentes Reutilizables en React JS
Descubre la Creación de Componenetes en React: Guía para Construir y Gestionar Componentes Reutilizables en Tus Proyectos de React JS
React vs Angular: ¿Cuál es Mejor?
.Descubre las diferencias clave entre React y Angular para determinar cuál es mejor para tus necesidades de desarrollo
Tabla de contenido
¿Qué es Redux?
Principales Características de Redux
¿Por qué Usar Redux?
Cómo Integrar Redux con React
Configuración Inicial del Proyecto
Instalación de Dependencias Necesarias
Configuración de Store de Redux
Conceptos Clave de Redux
Action
Acciones con Datos
Reducer
Combinación de Reducers
Store de Redux
Funciones del Store en Redux
Herramientas y extensiones útiles
Redux DevTools
Redux Toolkit
Otras bibliotecas complementarias
Mejores prácticas y patrones comunes
Organización del código
Performance y optimización
Testing de aplicaciones Redux
Conviertete en un experto de React
Descubre la formación a tu medida
Rellena el formulario para obtener más información sobre los cursos.
Tamaño de la empresa *
Términos y condiciones *