Manejo del estado con Redux y Angular
En este curso aprenderás a controlar el estado global de nuestra aplicación Angular de eCommerce mediante Redux a...
¿Estás cansado de escribir tanto código repetitivo con Redux? Redux Toolkit ofrece una forma más simple y eficiente de gestionar el estado de tus aplicaciones. En esta guía paso a paso aprenderás cómo hacer la transición y mejorar tu flujo de trabajo en el proceso.
Has estado usando Redux durante años, pero con el crecimiento de tus proyectos, te das cuenta de que gestionar el estado se vuelve cada vez más complejo y tedioso.
Entonces, escuchas sobre Redux Toolkit, una versión más optimizada y fácil de usar.
Migrar puede sonar intimidante, pero en esta guía paso a paso te mostraremos cómo hacerlo sin complicaciones, mejorando tu flujo de trabajo y reduciendo el código repetitivo.
Redux Toolkit (RTK) es una mejora significativa sobre la implementación tradicional de Redux, ya que reduce el código repetitivo (boilerplate) y facilita la configuración. Ofrece herramientas como createSlice
y createAsyncThunk
para simplificar la creación de acciones y reducers, y utiliza Immer
para manejar la inmutabilidad de forma eficiente.
RTK mejora el rendimiento, es más fácil de escalar y mantener, y sigue patrones consistentes que facilitan la colaboración en equipos grandes. Además, cuenta con una documentación completa y el respaldo de una comunidad activa, lo que lo convierte en la opción ideal para proyectos modernos que utilizan Redux.
Si te interesa profundizar más en las ventajas que ofrece Redux Toolkit, te recomendamos leer el post anterior sobre Redux Toolkit: Simplifica la gestión del estado. Ahí exploramos en detalle los beneficios clave y cómo Redux Toolkit puede mejorar tu flujo de trabajo.
Migrar de Redux a Redux Toolkit no tiene por qué ser un proceso complicado.
En esta sección, te guiaremos cada paso necesario para realizar esta transición de manera simple y efectiva.
Antes de comenzar con la migración, es fundamental revisar la configuración actual de Redux en tu proyecto. Asegúrate de que el código esté bien organizado y documentado, y toma nota de todos los reducers, actions, y thunks que ya tienes implementados.
Esto te dará un punto de referencia para comenzar la migración y te ayudará a identificar cualquier área que pueda requerir una especial atención durante el proceso.
El primer paso concreto en la migración es instalar Redux Toolkit en tu proyecto. Puedes hacerlo utilizando npm o yarn:
npm install @reduxjs/toolkit
O si usas Yarn:
yarn add @reduxjs/toolkit
Esta instalación te proporcionará todas las herramientas necesarias para empezar a refactorizar tu código existente hacia una implementación más moderna y eficiente.
Uno de los cambios clave al migrar a Redux Toolkit es la reconfiguración del store. En lugar de utilizar createStore
de Redux, usarás configureStore
de Redux Toolkit. Este método no solo simplifica la configuración, sino que también aplica automáticamente las mejores prácticas, como la inclusión de middleware útil como redux-thunk
y herramientas de depuración.
Ejemplo de reconfiguración del store:
import { configureStore } from "@reduxjs/toolkit";
import counterReducer from "./features/counter/counterSlice";
export const store = configureStore({
reducer: {
counter: counterReducer,
},
});
createSlice
Uno de los mayores beneficios de Redux Toolkit es la función createSlice
, que combina la lógica del reducer y las acciones en un solo lugar. Esto reduce significativamente la cantidad de código y hace que la lógica sea más fácil de comprender.
Ejemplo de refactorización reducers:
import { createSlice } from "@reduxjs/toolkit";
export const counterSlice = createSlice({
name: "counter",
initialState: { value: 0 },
reducers: {
increment: (state) => {
state.value += 1;
},
decrement: (state) => {
state.value -= 1;
},
},
});
export const { increment, decrement } = counterSlice.actions;
export default counterSlice.reducer;
createAsyncThunk
Si tu aplicación utiliza thunks para manejar operaciones asincrónicas, Redux Toolkit ofrece createAsyncThunk
, una forma más sencilla y estructurada de definir estas acciones. createAsyncThunk
gestiona automáticamente los ciclos de vida de la acción (pendiente, cumplida, rechazada) y actualiza el estado en consecuencia.
Ejemplo de migración thunks:
import { createAsyncThunk } from "@reduxjs/toolkit";
export const fetchUser = createAsyncThunk("users/fetchUser", async (userId) => {
const response = await fetch(`/api/users/${userId}`);
return response.json();
});
Después de migrar los reducers y thunks, necesitarás actualizar los componentes que interactúan con el store de Redux. Asegúrate de ajustar las importaciones y adaptarlas a la nueva estructura. Además, revisa el uso de useSelector
y useDispatch
para asegurarte de que sigan funcionando correctamente con las nuevas configuraciones y slices.
Redux Toolkit proporciona codemods, un conjunto de herramientas automatizadas diseñadas para modificar el código de manera eficiente y segura. Este cojunto de herramientas es especialmente útil durante procesos de migración complejos, como cuando se quiere actualizar un proyecto de Redux que utiliza patrones más antiguos a la sintaxis más moderna y recomendada de Redux Toolkit. Uno de los casos de uso más comunes es la migración de la sintaxis de objeto deprecated
a la sintaxis de builder
, que es más robusta y flexible. Para facilitar este proceso, puedes utilizar el siguiente comando en la terminal:
npx @reduxjs/rtk-codemods createReducerBuilder ./src
Este comando busca y transforma automáticamente las partes de tu código que todavía utilizan la sintaxis de objeto antigua, actualizándolas a la nueva sintaxis de builder
. Esto no solo ahorra tiempo, sino que también minimiza el riesgo de errores manuales durante la migración. Es especialmente beneficioso en proyectos grandes, donde realizar estos cambios manualmente podría ser tedioso y propenso a errores.
Al utilizar codemods, puedes asegurarte de que tu aplicación sigue las mejores prácticas de Redux Toolkit, aprovechando todas sus ventajas, como la reducción del código repetitivo (boilerplate), la simplificación en el manejo de la lógica asíncrona y una experiencia de desarrollo más fluida y eficiente, sin embargo, al tratarse de un proceso automatizado debe prestar especial atención a los cambios que realice en tu código.
Una vez completada la migración, es imprescindible realizar pruebas exhaustivas para garantizar que todo funcione como se espera. Ejecuta tus pruebas unitarias y de integración para identificar posibles errores o comportamientos inesperados.
Si encuentras problemas, ajusta el código según sea necesario, aprovechando las herramientas de depuración como Redux DevTools para diagnosticar y resolver los problemas.
Para comprobar que Redux Toolkit está funcionando correctamente, puedes escribir pruebas unitarias que verifiquen el comportamiento de los reducers y las acciones generadas por createSlice
.
Migración gradual: Si trabajas en una aplicación de un tamaño considerable, considera realizar la migración de forma gradual. Comienza migrando un módulo o slice a la vez, probando y verificando que todo funcione antes de continuar con el siguiente. Esto reducirá el riesgo de introducir errores y facilitará la resolución de problemas si algo no funciona como se espera.
Mantenimiento del código: Durante y después de la migración, asegúrate de mantener el código limpio y bien documentado. Aprovecha la estructura modular que ofrece Redux Toolkit para organizar tu código de manera que sea fácil de entender y mantener. Además, actualiza la documentación interna para reflejar cualquier cambio en la arquitectura del estado y las operaciones asincrónicas.
Rendimiento optimizado: Redux Toolkit incluye varias optimizaciones de rendimiento, como la inmutabilidad automática del estado con Immer. Sin embargo, siempre es recomendable monitorear el rendimiento después de la migración para asegurarte de que la aplicación siga funcionando de manera eficiente. Además, debes considerar el uso de herramientas de monitoreo de rendimiento y análisis para detectar posibles cuellos de botella.
Documentar el proceso de migración: Documenta las razones, los pasos y las decisiones tomadas durante la migración para ayudar a otros desarrolladores a entender los cambios y para facilitar futuras actualizaciones o migraciones.
Revisión del proyecto actual: Analiza la estructura actual de tu proyecto Redux, identificando los reducers, actions, thunks, y cualquier middleware personalizado que estés utilizando.
Instala Redux Toolkit y su dependencia:
npm install @reduxjs/toolkit react-redux
git checkout -b migration-to-redux-toolkit
// authReducer.js (Antes de la migración)
const initialState = {
isAuthenticated: false,
user: null,
};
function authReducer(state = initialState, action) {
switch (action.type) {
case "LOGIN_SUCCESS":
return {
...state,
isAuthenticated: true,
user: action.payload,
};
case "LOGOUT":
return initialState;
default:
return state;
}
}
export default authReducer;
createSlice
para migrar el reducer:
// authSlice.js (Después de la migración)
import { createSlice } from "@reduxjs/toolkit";
const authSlice = createSlice({
name: "auth",
initialState: {
isAuthenticated: false,
user: null,
},
reducers: {
loginSuccess(state, action) {
state.isAuthenticated = true;
state.user = action.payload;
},
logout(state) {
state.isAuthenticated = false;
state.user = null;
},
},
});
export const { loginSuccess, logout } = authSlice.actions;
export default authSlice.reducer;
// store.js (Antes de la migración)
import { createStore } from "redux";
import authReducer from "./authReducer";
const store = createStore(authReducer);
export default store;
// store.js (Después de la migración)
import { configureStore } from "@reduxjs/toolkit";
import authReducer from "./authSlice";
const store = configureStore({
reducer: {
auth: authReducer,
},
});
export default store;
// authActions.js (Antes de la migración)
export const loginUser = (credentials) => {
return async (dispatch) => {
try {
const user = await api.login(credentials);
dispatch({ type: "LOGIN_SUCCESS", payload: user });
} catch (error) {
console.error(error);
}
};
};
createAsyncThunk
para definir el thunk en Redux Toolkit:
// authSlice.js (Después de la migración)
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import api from "../api";
export const loginUser = createAsyncThunk(
"auth/loginUser",
async (credentials, { rejectWithValue }) => {
try {
const user = await api.login(credentials);
return user;
} catch (error) {
return rejectWithValue(error.response.data);
}
}
);
const authSlice = createSlice({
name: "auth",
initialState: {
isAuthenticated: false,
user: null,
status: "idle",
error: null,
},
reducers: {
logout(state) {
state.isAuthenticated = false;
state.user = null;
},
},
extraReducers: (builder) => {
builder
.addCase(loginUser.pending, (state) => {
state.status = "loading";
})
.addCase(loginUser.fulfilled, (state, action) => {
state.status = "succeeded";
state.isAuthenticated = true;
state.user = action.payload;
})
.addCase(loginUser.rejected, (state, action) => {
state.status = "failed";
state.error = action.payload;
});
},
});
export const { logout } = authSlice.actions;
export default authSlice.reducer;
// authSelectors.js
export const selectIsAuthenticated = (state) => state.auth.isAuthenticated;
export const selectUser = (state) => state.auth.user;
// LoginComponent.js (Antes de la migración)
import React from "react";
import { useDispatch } from "react-redux";
import { loginUser } from "./authActions";
const LoginComponent = () => {
const dispatch = useDispatch();
const handleLogin = (credentials) => {
dispatch(loginUser(credentials));
};
return (
<button
onClick={() => handleLogin({ username: "user", password: "pass" })}
>
Login
</button>
);
};
export default LoginComponent;
// LoginComponent.js (Después de la migración)
import React from "react";
import { useDispatch } from "react-redux";
import { loginUser } from "./authSlice";
const LoginComponent = () => {
const dispatch = useDispatch();
const handleLogin = (credentials) => {
dispatch(loginUser(credentials));
};
return (
<button
onClick={() => handleLogin({ username: "user", password: "pass" })}
>
Login
</button>
);
};
export default LoginComponent;
Migrar de Redux a Redux Toolkit puede parecer un reto, pero los beneficios en términos de simplicidad, mantenibilidad y rendimiento hacen que el esfuerzo valga la pena.
Esta librería no solo simplifica la configuración y el uso de Redux, sino que también introduce patrones modernos que facilitan la escalabilidad y el mantenimiento a largo plazo.
Recuerda que en OpenWebinars, dispones de la ruta de aprendizaje Desarrollador frontend con React, en la que profudizarás en el uso de Redux para manejar el estado en aplicaciones basadas en React.
También te puede interesar
En este curso aprenderás a controlar el estado global de nuestra aplicación Angular de eCommerce mediante Redux a...
Uno de los perfiles más demandando por las empresas.
Redux Toolkit permite gestionar el estado de forma más clara y eficiente, minimizando el código repetitivo. Aprende cómo esta herramienta está cambiando...