Introducción a Redux
Tags: javascript, react, typescript
Published: 2022-03-18 21:26:02

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](http://facebook.github.io/flux/) la cual es una arquitectura
que facebook utilizaba para construir sus aplicaciones web, pero tratando de reducir su complejidad tomando cosas de [Elm](https://guide.elm-lang.org/) 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.


```tsx
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](https://github.com/pmndrs/zustand), [recoil](https://recoiljs.org/) 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](https://blog.logrocket.com/when-and-when-not-to-use-redux-41807f29a7fb/)


## 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:

![Redux view](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/64n2ygztr2gn9b2n7h7c.png)

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

```ts
interface Action {
  type: string;
  payload: any;
}
```
Como sabemos hasta ahora, redux está inspirado en [flux](http://facebook.github.io/flux/) y de hecho heredó el estándar de [acción](https://github.com/redux-utilities/flux-standard-action).

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](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce) 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:


```ts
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:_

```ts
const initalState = {
  eatCount: 0,
  sleepCount: 0,
  readCount: 0,
};
```

Tenemos un objeto que almacena las veces que hemos realizado una determinada acción.

_Acciones:_

```ts
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:_


```ts
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`.

```ts
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:_

```ts
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.

```ts
const result = ACTIONS.reduce(logger(reducer), initalState);
```
Salida:

![logs](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4wmaqc1azsg4lndvu1xa.png)

Hasta aquí la introducción a redux :). Happy Coding
 
link del ejemplo: https://stackblitz.com/edit/react-ts-ur6qfs?file=index.tsx