Introducción
NgRx Effects es una biblioteca que se utiliza junto con NgRx Store para manejar efectos secundarios en aplicaciones Angular. Los efectos secundarios son operaciones que no afectan directamente al estado de la aplicación, como llamadas a APIs, operaciones de enrutamiento, o cualquier otra operación asíncrona. NgRx Effects permite gestionar estas operaciones de manera reactiva y declarativa utilizando Observables.
Objetivos
- Comprender qué son los efectos en NgRx.
- Aprender a crear y manejar efectos utilizando NgRx Effects.
- Integrar efectos en una aplicación Angular para manejar operaciones asíncronas.
Conceptos Clave
- Efectos (Effects): Son clases que escuchan acciones despachadas al Store y realizan operaciones asíncronas en respuesta a esas acciones.
- Actions: Son objetos que describen eventos que ocurren en la aplicación.
- Observables: Son secuencias de eventos que se pueden observar y manejar de manera reactiva.
Instalación
Antes de comenzar, asegúrate de tener NgRx Effects instalado en tu proyecto Angular. Puedes instalarlo utilizando npm:
Creación de Efectos
Paso 1: Definir Acciones
Primero, definimos las acciones que desencadenarán los efectos. Por ejemplo, si estamos manejando una lista de productos, podríamos tener acciones para cargar productos, cargar productos exitosamente y manejar errores.
// actions/product.actions.ts import { createAction, props } from '@ngrx/store'; export const loadProducts = createAction('[Product] Load Products'); export const loadProductsSuccess = createAction( '[Product] Load Products Success', props<{ products: Product[] }>() ); export const loadProductsFailure = createAction( '[Product] Load Products Failure', props<{ error: any }>() );
Paso 2: Crear el Efecto
A continuación, creamos una clase de efectos que escuche la acción loadProducts
y realice una llamada a una API para cargar los productos.
// effects/product.effects.ts import { Injectable } from '@angular/core'; import { Actions, createEffect, ofType } from '@ngrx/effects'; import { ProductService } from '../services/product.service'; import { loadProducts, loadProductsSuccess, loadProductsFailure } from '../actions/product.actions'; import { catchError, map, mergeMap } from 'rxjs/operators'; import { of } from 'rxjs'; @Injectable() export class ProductEffects { constructor( private actions$: Actions, private productService: ProductService ) {} loadProducts$ = createEffect(() => this.actions$.pipe( ofType(loadProducts), mergeMap(() => this.productService.getAll().pipe( map(products => loadProductsSuccess({ products })), catchError(error => of(loadProductsFailure({ error }))) ) ) ) ); }
Paso 3: Registrar los Efectos
Finalmente, registramos los efectos en el módulo de efectos de NgRx.
// app.module.ts import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { StoreModule } from '@ngrx/store'; import { EffectsModule } from '@ngrx/effects'; import { ProductEffects } from './effects/product.effects'; import { productReducer } from './reducers/product.reducer'; @NgModule({ declarations: [AppComponent], imports: [ BrowserModule, StoreModule.forRoot({ products: productReducer }), EffectsModule.forRoot([ProductEffects]) ], providers: [], bootstrap: [AppComponent] }) export class AppModule {}
Ejercicio Práctico
Ejercicio
- Objetivo: Crear un efecto que cargue una lista de usuarios desde una API y maneje los resultados exitosos y los errores.
- Pasos:
- Define las acciones
loadUsers
,loadUsersSuccess
yloadUsersFailure
. - Crea un servicio
UserService
que tenga un métodogetAll
para obtener los usuarios. - Crea una clase de efectos
UserEffects
que escuche la acciónloadUsers
y realice la llamada a la API. - Registra los efectos en el módulo de efectos de NgRx.
- Define las acciones
Solución
Definir Acciones
// actions/user.actions.ts import { createAction, props } from '@ngrx/store'; export const loadUsers = createAction('[User] Load Users'); export const loadUsersSuccess = createAction( '[User] Load Users Success', props<{ users: User[] }>() ); export const loadUsersFailure = createAction( '[User] Load Users Failure', props<{ error: any }>() );
Crear el Servicio
// services/user.service.ts import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; import { User } from '../models/user.model'; @Injectable({ providedIn: 'root' }) export class UserService { private apiUrl = 'https://api.example.com/users'; constructor(private http: HttpClient) {} getAll(): Observable<User[]> { return this.http.get<User[]>(this.apiUrl); } }
Crear la Clase de Efectos
// effects/user.effects.ts import { Injectable } from '@angular/core'; import { Actions, createEffect, ofType } from '@ngrx/effects'; import { UserService } from '../services/user.service'; import { loadUsers, loadUsersSuccess, loadUsersFailure } from '../actions/user.actions'; import { catchError, map, mergeMap } from 'rxjs/operators'; import { of } from 'rxjs'; @Injectable() export class UserEffects { constructor( private actions$: Actions, private userService: UserService ) {} loadUsers$ = createEffect(() => this.actions$.pipe( ofType(loadUsers), mergeMap(() => this.userService.getAll().pipe( map(users => loadUsersSuccess({ users })), catchError(error => of(loadUsersFailure({ error }))) ) ) ) ); }
Registrar los Efectos
// app.module.ts import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { StoreModule } from '@ngrx/store'; import { EffectsModule } from '@ngrx/effects'; import { UserEffects } from './effects/user.effects'; import { userReducer } from './reducers/user.reducer'; @NgModule({ declarations: [AppComponent], imports: [ BrowserModule, StoreModule.forRoot({ users: userReducer }), EffectsModule.forRoot([UserEffects]) ], providers: [], bootstrap: [AppComponent] }) export class AppModule {}
Conclusión
NgRx Effects es una herramienta poderosa para manejar efectos secundarios en aplicaciones Angular de manera reactiva y declarativa. Al utilizar NgRx Effects, puedes mantener tu lógica de efectos secundarios separada de tu lógica de estado, lo que resulta en un código más limpio y mantenible. En este módulo, aprendiste a crear y manejar efectos utilizando NgRx Effects, y cómo integrarlos en una aplicación Angular.
Curso de Angular 2+
Módulo 1: Introducción a Angular
- ¿Qué es Angular?
- Configuración del Entorno de Desarrollo
- Tu Primera Aplicación Angular
- Arquitectura de Angular
Módulo 2: Conceptos Básicos de TypeScript
- Introducción a TypeScript
- Variables y Tipos de Datos en TypeScript
- Funciones y Funciones Flecha
- Clases e Interfaces
Módulo 3: Componentes y Plantillas
- Creación de Componentes
- Plantillas de Componentes
- Estilos de Componentes
- Interacción entre Componentes
Módulo 4: Directivas y Pipes
Módulo 5: Servicios e Inyección de Dependencias
- Introducción a los Servicios
- Creación y Uso de Servicios
- Inyección de Dependencias
- Inyectores Jerárquicos
Módulo 6: Enrutamiento y Navegación
Módulo 7: Formularios en Angular
- Formularios Basados en Plantillas
- Formularios Reactivos
- Validación de Formularios
- Formularios Dinámicos
Módulo 8: Cliente HTTP y Observables
- Introducción al Cliente HTTP
- Realizando Solicitudes HTTP
- Manejo de Respuestas HTTP
- Uso de Observables
Módulo 9: Gestión de Estado
- Introducción a la Gestión de Estado
- Uso de Servicios para la Gestión de Estado
- NgRx Store
- NgRx Effects