State Management en Angular: Ngxs

Un manejador de estados similar al flow de redux para Angular

Ngxs es un state management desarrollado para Angular el cual contiene un flow similar al de redux
Recordemos que un manejador de estados es una herramienta que nos permite centralizar los estados de nuestras aplicaciones, lo cual facilita al acceso de los datos sin la necesidad de estar accediendo a los mismos de formas pocas fluidas, esto sucede más que todo cuando la aplicación crece mucho. A continuación muestro el flujo de datos que aplica, esta imágen es cortesía de la documentación oficial de Ngxs el cual puedes acceder AQUÍ
ngxs1
Analizando el flujo encontramos: Desde el componente se dispara una acción donde el mismo verifica con el backend o con plugins instalados la data que debe obtener, cuando la obtiene muta la misma y se la pasa al store y el store devuelve el nuevo estado al componente.
Ejemplo: Cuando guardamos datos desde un formulario, al presionar el botón "guardar" se dispara la acción que interactura con las entidades (plugins, apis, otros) y al obtener la respuesta la envía al store y el store devuelve el nuevo estado (la lista de datos con el nuevo dato agregado)
Veamos en código el ejemplo: Vamos a usar el mismo proyecto explicado en los post anteriores: Introducción a Angular y Inputs y Outputs Recordando que pueden clonar dicho proyecto AQUÍ
Instalamos nuestras dependencias de la siguiente forma:
npm install @ngxs/store --save
Es importante que, para que puedas verificar el comportamiento del estado al momento de desarrollar instales los siguientes plugins:
npm install @ngxs/devtools-plugin
npm install @ngxs/logger-plugin
Algo que te recomiendo es instalar el CLI de Ngxs lo cual te va ahorrar mucho tiempo a la hora de desarrollar: npm install @ngxs/cli -g
Para implementar Ngxs en nuestro proyecto debemos configurarlo en app.module.ts de la siguiente forma:
ngxs9
En este proyecto vamos hacer el crud de proveedores el cual se va alimentar de un servicio, no vamos a consumir un API por temas de agilidad pero vamos a harcodear los datos en dicho servicio. Primero que nada vamos a construir nuestro state Management para providers: a través del CLI de Ngxs ejecutamos: ngxs --name providers --directory src
ngxs2
Este comando me ha creado la carpeta state dentro de src y contiene: providers.action.ts la cual se encarga de configurar y ejecutar las acciones que vienen de los componentes, providers.sate.spec.ts que se encarga de ejecutar los test y y provider.state.ts que se encarga de configurar los estados que cada acción manipula.
providers.action.ts
ngxs3
ngxs3
Las acciones que vamos a ejecutar se basan en un crud y por ello configuramos las funciones pertinentes a cada item. Además en este caso llamamos a la interfaz provider que tiene definida nuestra entidad.
providers.state.ts
ngxs5
Importamos los módulos que necesitamos tanto del core de angular, de ngxs, las acciones que hemos definido y los servicios que usaremos.
Vemos una clase ProviderStateModel que va configurar el estado inicial de nuestro módulo, en este caso tenemos un array tipo Provider llamado providers y un string llamado selectedProvider (que a lo largo del tutorial no lo usamos, pero que nos puede servir para tomar solamente un record individual y ejecutar acciones sobre dicho dato)
Más adelante vemos un decorador @State que es necesario para que el Angular lo identifique y trabaje sobre las funciones que cambian los estados de forma correcta.
Luego configuramos nuestra clase, constructor y funciones.
ngxs6
En el constructor inyectamos el módulo de servicios que luego vamos a configurar, este servicio va interacturar entre la data y el store.
El decordador @selector es parte de @ngxs/store y nos permite configurar un "puente" entre el estado y el componente, en este caso escribimos una función getProviderList que va obtener la lista de proveedores y que en el componente vamos a llamar de forma directa.
Después, empezamos a escribir nuestras funciones correspondientes a cada acción (addProvider, UpdateProvider, DeleteProvider, GetProvider) Explicaremos AddProvider.
AddProvider: Ngxs permite configurar dentro de sus funciones para manejar los estados features que son adecuados para cada tarea, en este caso sería getState y patchState. Ambos nos permiten manipular la data (el payload) que viene de la acción y configurar el nuevo estado resultante a través de un contexto. Este contexto va recibir un observable. Ese observable es la respuesta del servicio a la cual se le pasa el payload en conjunto con los features de ngxs (getState y patchState)
Si, es un poco confuso al principio pero la clave para entender este proceso es ir función por función y entender qué hace cada cosa.
Además, vemos dos funciones adicionales: pipe y tap. Pipe permite agrupar funciones para luego ejecutarlas y tap maneja datos de forma reactiva y devuelve un observable. El observable que devuelve en este caso es la copia del estado anterior y el payload del nuevo estado, es decir, la lista de providers con el nuevo dato que se almacenó. Las demás funciones que manejan los estados para cada acción pueden verlas AQUÍ
Ya teniendo nuestro store configurado vamos a crear nuestro servicio. El servicio no es más que funciones que interactuan directamente con nuestras APIS o con datos harcodeados, como en este caso:
ngxs7
Ya teniendo nuestro store y nuestro servicio listo vamos a los componentes, en este caso hemos creado providers (padre) y providers-list (hijo) los cuales van a intercambiar datos a través de inputs y outputs. Recuerda que para entender estos puntos puedes ir al POST ANTERIOR
providers.component.ts
ngxs8
Primero importamos los módulos necesarios (ngxs, servicios, acciones, interface) y luego configuramos nuestra clase. En la clase vemos lo siguiente en la linea 16:
@Select Este decorador toma el estado configurado por @Selector de nuestro archivo provider.state.ts del store para luego manipularlo (enviarlo al template) y en nuestro constructor en la linea 19 ejecutamos la acción que llama a la lista de providers. Mejor dicho, la acción sale en la linea 19 y culmina en la linea 16 cuando pasa por todo el proceso. Para el resto de las funciones del componente pasa lo mismo, ejecutamos un Dispatch y el nuevo estado va devolver la lista de providers con el nuevo dato almacenado, pueden ver el archivo AQUÍ
Nuestro template es casi igual a los que hemos visto pero cabe acotar que en la linea 32 le estamos envíando al componente hijo la lista de providers a través del value providers$
ngxs10
Entonces, en resumen: Ngxs nos permite tener un store con un flujo de datos simple: Componentes ejecutan acciones que iteran con los servicios y que devuelve un nuevo estado. Cabe recordar que los templates y la formas de pasar datos entre inputs y outputs es igual.
Espero que les sirva y si, es confuso, lo importante es ir entendiendo los conceptos por separados y luego practicar.
Pueden ver el sistema corriendo AQUÍ
Saludos!
#Typescript
#Angular
#Ngxs
#StateManagement
Comentarios: Pronto!