Gestión del estado en Angular sin ngrx

0
5483

En este tutorial vamos a hablar de cómo gestionar el estado de nuestras aplicaciones Angular sin tener que recurrir a la complejidad de la librería ngrx.

Índice de contenidos


1. Entorno

Este tutorial está escrito usando el siguiente entorno:

  • Hardware: portátil Mac Book Pro 15″ (2,3 Ghz Intel Core i7, 16 GB DDR3)
  • Sistema operativo: macOS Sierra
  • @angular/cli 1.2.6
  • @angular 4.3.3


2. Introducción

No es que yo tenga nada en contra del uso de la librería ngrx para la gestión del estado en aplicaciones con Angular, de hecho se está convirtiendo en un estándar de facto. Lo que pasa es que por más blogs que leo y más charlas hasta del mismísimo Victor Savkin, menos intuitivo me parece su uso y más separado de la implementación «normal» de una aplicación de Angular lo veo. Para mí es como un cambio completo de paradigma que te obliga a desarrollar como dicta la librería y lo veo poco intuitivo y mantenible (opinión personal).

Lo que es innegable son las ventajas que aporta tener separado el estado de la aplicación como una única fuente de verdad absoluta a la que todos consultan y donde todos modifican. Es por ello que leyendo un poco más sobre el tema me encontré con el Angular Model Pattern que consta de un único fichero de 1.07 Kb que haciendo uso de la programación reactiva y más concretamente del BehaviorSubject permite mantener el estado de la aplicación de una forma que a mi parecer es más intuitiva y que se adapta mejor a la forma de implementar las aplicaciones con Angular.


3. Vamos al lío

El propio autor de la librería nos ofrece dos opciones para su uso: bien instalando la dependencia ngx-model

$> npm install --save ngx-model

o simplemente creando nosotros el siguiente servicio:

import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';

export class Model T) {
    this._data = new BehaviorSubject(initialData);
    this.data$ = this._data.asObservable()
      .map(data => immutable
        ? clone ? clone(data) : JSON.parse(JSON.stringify(data))
        : data);
  }

  get(): T {
    return this._data.getValue();
  }

  set(data: T) {
    this._data.next(data);
  }

}

export class ModelFactory

Lo que hace es, a través de genéricos, generalizar la creación de BehaviorSubject en base al tipo de datos que necesitemos, proporcionando métodos para la consulta y modificación de los datos del modelo y mejoras para hacer el clonado de los objetos y mantener la inmutabilidad.

De esta forma podemos instanciar en cualquier módulo el provider:

@NgModule({
  providers: [MODEL_PROVIDER]
})

o si hacemos uso de la librería:

import { NgxModelModule } from 'ngx-model';

@NgModule({
  imports: [NgxModelModule]
})

Y ya podemos hacer uso de esta clase de instanciación de modelo. Por ejemplo, si queremos almacenar el estado de un usuario, podríamos crear la interfaz con sus datos:

export interface User {
  login: string;
  name: string;
  avatar: string;
  admin: boolean;
}

Y crear un servicio de modelo donde utilizar esta interfaz para instanciar el modelo de User e implementar todos los métodos que cambian y consultan los datos del modelo.

import { Observable } from 'rxjs/Observable';
import { Injectable } from '@angular/core';
import { Model, ModelFactory } from 'ngx-model';

import { User } from './list-users/user';

@Injectable()
export class CurrentUserModelService {

  private model: Model

Ahora en los componentes o servicios que se quiera consultar/modificar el estado del usuario solo se tiene que inyectar el servicio CurrentUserModelService y hacer uso de los métodos creados. A continuación vemos un ejemplo de componente que consulta los datos para mostrarlos por pantalla:

@Component({
      selector: 'app-user',
      template: `
        <div *ngIf="user$ | async as user">
          

{{user.login}}

{{user.name}}

{{user.admin}}

<img [src]="user.avatar">

Nota: fíjate que estamos haciendo uso del observable para suscribirnos dentro del método ngOnInit a los cambios que se produzcan en el objeto, de forma que si otro componente hiciera uso del método setUser para modificar la información, inmediatamente este componente mostraría esa información de forma reactiva, es decir, sin tener que refrescar la aplicación. Y, si hubiera más de un componente suscrito, toda la información cambiaría al mismo tiempo.


4. Conclusiones

Como ves la programación reactiva vuelve en nuestra ayuda para facilitarnos de una forma muy cómoda, limpia y elegante un elemento nada trivial en nuestras aplicaciones como es la gestión del estado y la actualización de todos los componentes una vez se cambia el estado.

ngrx te proporciona esto mismo y muchas más cosas pero de una forma mucho más encorsetada y a mi modo de ver más confusa y menos mantenible.

Recordad que esta técnica y otras muchas más las encontraréis en la guía práctica de Angular y también ofrecemos cursos in-house y online.

Cualquier duda o sugerencia en la zona de comentarios.

Saludos.

DEJA UNA RESPUESTA

Por favor ingrese su comentario!

He leído y acepto la política de privacidad

Por favor ingrese su nombre aquí

Información básica acerca de la protección de datos

  • Responsable:
  • Finalidad:
  • Legitimación:
  • Destinatarios:
  • Derechos:
  • Más información: Puedes ampliar información acerca de la protección de datos en el siguiente enlace:política de privacidad