Redux es una de las librerías más utilizadas al momento de pensar en el manejo de estado de nuestra aplicación.
Criticada y amada por muchos desarrolladores. Hace que haya diferentes opiniones acerca del uso de redux.
Dentro de esta serie de artículos quiero compartir desde mi perspectiva el uso de redux, aclaro que no profundizaré
en algunos conceptos, pero dejaré algunas referencias para que puedas leerlo.
¿Que es redux?
Redux es una librería que nos permite manejar el estado de nuestra aplicación web.
La idea detrás de redux es que este puede contener la información predecible del estado de nuestras aplicaciones web.
La construcción de redux fue influenciada por flux la cual es una arquitectura
que facebook utilizaba para construir sus aplicaciones web, pero tratando de reducir su complejidad tomando cosas de Elm el cual es un lenguaje funcional que se compila a javascript.
¿Que es el estado?
Cuando no referimos al estado de nuestra aplicación nos podemos referir a como los datos que tenemos son reflejados en nuesta apliación web.
Esto asegura que el usuario siempre está sincronizado con el estado interno de nuestra aplicación.
Una de la gran ventaja de los frameworks es que facilitan el control de estos datos a travéz de algoritmos que facilitan la detección de cambios.
Estado local:
En react el estado local de un componente puede ser manejar con useState
en el caso de utilizar funciones.
import { useState } from "react";
const LocalState = () => {
const [hi, sayHi] = useState("");
return (
<div>
<button onClick={() => sayHi("Hello")}>Say Hi</button>
<h1>{hi}</h1>
</div>
);
};
De esta función entendemos que hi
es el estado actual, y la forma de como actualizarlo este estado es con la función sayHi
.
Podemos imaginar a redux de igual manera, pero en este caso el estado no solo será un componente, será de toda la aplicación y esto implica que podemos suscribirnos a los cambios del estado desde cualquier componente sin importar su jerarquía y de igual manera afectarlo.
¿Por que usar redux?
Utilizar redux en nuestras aplicaciones se ha vuelto cuestionable por las alternativas más livianas y fáciles de usar que existen, tales como; zuztand, recoil e incluso la api de Context
que ofrece el propio react. Me ahorraré este debate 😅 y lo sintetizaré en lo siguiente.
Si tenemos un estado complejo, la capacidad de redux para describir que es lo que hace nuestra aplicación es increíble.
Puede ver todo el estado de la aplicación y las acciones que afectan este estado, de esta manera, abre la facilidad de poder agregar nuevas características.Redux incluye otros beneficios como el debugging, con herramientas de desarrollo que nos permite rastrear las acciones para poder encontrar mucho más rápido el origen de un error.
Redux es estricto con la estructura del código, eso quiere decir que cualquiera que sepa redux puede entender nuestra aplicación.
Posiblemente esta explicación quedo un poco corta, si ese es el caso, puedes leer el siguiente artículo de Christian Nwamba
Principios de redux
Junto con redux vienen ciertos principios que hay que tener en cuenta a la hora de utilizarlo. Los cuales son tres.
Única fuente de verdad
Toda la información estará guardada en único Store el cual expone una API para acceder a los datos. Esto facilita la depuración de la aplicación, tener un estado persistente, poder serializar el estado del servidor y guardarlo en el cliente.
El estado es de solo lectura
Este principio evita que tanto las vistas o las llamadas al server afecten el estado. Para hacerlo ello expresan un intento de transformar el estado por medio de acciones, las acciones son objetos planos que pueden ser serializados y
almacenados y depurarlos, gracias a este enfoque existen las Redux Dev Tools, donde tenemos todas las acciones que han sido despachadas.
Pero, ¿esto igual no es escriben en el estado?, La respuesta es no y se complementa con el siguiente principio.
Los cambios son hechos con funciones puras
Primero que nada, ¿Qué es una función pura?. Una función pura es una función que no tiene efectos secundarios, esto quiere decir que siempre que se tengan los mismos parámetros el resultado será siempre el mismo.
En redux estas funciones son llamadas reductores el cual recibe como primer parámetro el estado actual y como segundo parámetro
la acción. Podemos usar estos parámetros para retornar el siguiente estado de nuestra aplicación.
Dando respuesta a la anterior pregunta, no escribimos en el estado, si queremos cambiar algo, lo cambiamos por completo. A esto se conoce como inmutabilidad.
Conceptos
Para ir paso a paso y teniendolo como guia tomaré este diagrama:
Pasito a pasito, lo que se ven en el diagrama es como se comporta redux y como interactúan los elementos que lo componen.
Store: Previamente, ya se había adelanto lo que llegaría ser un store. El cual es un objeto que contiene el estado y métodos que nos ayudan a interactuar con este, como por ejemplo suscribirnos a los cambios o disparar una acción.
Acción: Las acciones son objetos planos que tienen la siguiente estructura
interface Action {
type: string;
payload: any;
}
Como sabemos hasta ahora, redux está inspirado en flux y de hecho heredó el estándar de acción.
La propiedad type
es de tipo string
y es el nombre de la acción que se está disparando, esta propiedad prácticamente describe de que trata el payload. Tener en cuenta que la propiedad es una constante, por ende debe ir en mayúscula, no es opcional, el payload sí.
De echo vamos a analizar este método, si no has usado Array.prototype.reduce
puedes echarle un vistazo a la documentación pero básicamente es una función al cual se le pasa dos parámetros, una función reductora y un estado inicial.
Por ejemplo, podemos utilizar reduce
para sumar todos los número de un array:
const nums = [1, 2, 3, 4, 5, 6, 7, 8];
const result = nums.reduce((prev, curr) => prev + curr, 0);
Una función reductura es una función pura que recibe el resultado que se obtiene de la ejecución de la función reductura anterior y el valor actual que la iteración.
Podemos hacer que esto nos ayude a comprender un poco redux. Atención al siguiente ejemplo.
Estado inicial:
const initalState = {
eatCount: 0,
sleepCount: 0,
readCount: 0,
};
Tenemos un objeto que almacena las veces que hemos realizado una determinada acción.
Acciones:
const ACTIONS = ["EAT", "SLEEP", "READ", "SLEEP", "EAT"];
Digamos que estas son las acciones que hemos realizado hasta el momento, ahora necesitamos un mecanismo que nos ayude a sumar estas acciones en el objeto.
Función reductora:
const reducer = (state, action) => {
switch (action) {
case "EAT": {
return {
...state,
eatCount: state.eatCount + 1,
};
}
case "SLEEP": {
return {
...state,
sleepCount: state.sleepCount + 1,
};
}
case "READ": {
return {
...state,
readCount: state.readCount + 1,
};
}
}
};
Notese que hemos cambiado los nombres de los parámetros de la función reductora prev -> state
y curr -> action
. Entonces tenemos mapeado cada acción a un proceso determinado. y retornamos un estado diferente.
Ahora ya tenemos lo suficiente para utilizar reduce
.
const result = ACTIONS.reduce(reducer, initalState);
/*
Output:
{
"eatCount": 2,
"sleepCount": 2,
"readCount": 1
}
*/
Ahora, ¿Cómo esto se asemeja a redux?, bueno, en redux en lugar de que estas acciones ocurran de manera síncrona, estas acciones ocurren de manera secuencial.
Las acciones se van disparando el Store
las escuchas y ejecuta el reducer correspondiente.
Middleware:
Si bien middleware es un concepto un poco amplio, podemos tener una pequeña introducción con el ejemplo que se acaba de ver.
Los middleware son funciones que puede tomar el control entre el viaje de
la acción hacia el reducer
. o del resultado del reducer hacia el store
.
Podemos usar el middleware para distintos casos, como hacer peticiones asincronas, como es el caso de reux-thunk
, pero uno de los más comunes es hacer un logging de las acciones.
Logger:
const logger = (reducer) => {
return (state, action) => {
const nextState = reducer(state, action);
console.log(action, "->", nextState);
return nextState;
};
};
Esta función lo que hace es tomar el reducer y retornar un nuevo reducer el cual ejecuta esta función para obtener el nuevo estado e imprimirlo en pantalla.
const result = ACTIONS.reduce(logger(reducer), initalState);
Salida:
Hasta aquí la introducción a redux :). Happy Coding
link del ejemplo: https://stackblitz.com/edit/react-ts-ur6qfs?file=index.tsx
Top comments (2)
El contenido pareciera estar bueno, pero tiene demasiados errores ortotipográficos y de estilo que hacen difícil entenderlo en definitiva.
Incluso, pareciera ser una mala traducción de algún artículo en inglés u otro idioma.
Hola, interesante, revisando el artículo, me doy cuenta de que si hay unos errores, pero ay una explicación para ello, y es simple, cuando estudio algo, me cuelgo de los conceptos para pasar a la práctica, siempre trato de compartir algo que pueda ser diferente, y la parte de los conceptos (puntos claves que creo que son importantes) siempre trato de ponerlos igual que las documentaciones, y como estoy aprendiendo inglés, trato de traducirlos yo mismo, mis aportes siempre son los ejemplos o explicaciones que hago yo mismo para complementar las documentaciones, y siempre aconsejo corrobar la información, porque contenido como este solo es una palanca para entender la tecnología y nunca va a sustituir la documentación, casi siempre me tomo el tiempo de revisar y poner las referencias, pero a veces implica tiempo, entiendo que eso puede perjudicar a alguien, por ende tendré un poco de cuidado, con respecto a "son una mala traducción de algún artículo" la respuesta es sí por lo mencionado anteriormente, ya que tengo que estudiar muchos artículos para que en mi mente pueda ordenar todo . Lo invito a nuestra comunidad, dictamos talleres y nos divertimos estudiando Discord. Bendiciones
Some comments have been hidden by the post's author - find out more