Utilitzant Redux amb Angular

How to Implement NGRX State Management in Angular Web Application

Taula de continguts

Avui aprendrem a introduir l’ús de la gestió de l’estat de REDUX en una aplicació web angular amb la biblioteca NGRX

L’equivalent REDUX per a Angular és NGRX .

També us pot interessar: “Unimedia nomenat com a líders tecnològics per Clutch”

A més, el nostre equip de desenvolupadors són experts en la creació de software personalitzat segons els requisits del projecte.

Veurem cada bloc de construcció de NGRX pas a pas

Diagrama del cicle de vida de la gestió de l'estat de NgRx
Font: https://ngrx.io/

Botiga

El magatzem és un contenidor d’estat controlat dissenyat per ajudar a escriure aplicacions de rendiment i escalables a sobre d’Angular.

Efectes

Els efectes utilitzen fluxos per proporcionar noves fonts d’accions. Per modificar l’estat en funció d’interaccions externes, com ara sol·licituds de xarxa, missatges de connexió web i esdeveniments basats en el temps. Per tant, són el mètode preferit per obtenir dades i mantenir part de la lògica de l’aplicació.

Selectors

Els Selectors són funcions pures utilitzades per obtenir porcions de l’estat de la botiga. Així, seleccionen peces d’informació de la botiga que seran consumides per altres parts de la lògica de l’aplicació.

Reductors

Els reductors de NgRx són els responsables de gestionar les transicions d’un estat al següent a la vostra aplicació. Les funcions reductores gestionen aquestes transicions determinant quines accions s’han de gestionar en funció del tipus d’acció. En altres paraules, reben accions amb una càrrega útil de dades i canvien l’estat emmagatzemant les dades noves com es desitgi.

Després d’entendre els blocs bàsics de la gestió de l’estat NGRX, ara construirem una aplicació de xat petita d’exemple amb la gestió de l’estat NGRX.

Des de llavors, ja hem creat una aplicació de xat anteriorment a una publicació anterior aquí . Com a resultat, introduirem la gestió de l’estat NGRX per actualitzar la interfície d’usuari mentre s’envia/recep el missatge.

https://www.unimedia.tech/2020/11/27/aws-amplify-with-angular-chat/

1. Configurar el projecte

/** Clone Repo */
git clone https://github.com/unimedia-technology/amplify-chat-angular.git

/** Enter into project directory */
cd amplify-chat-angular

/** Install the dependencies */
npm i

/** Create a new git branch */
git checkout ngrx

2. Instal·lar les dependències NGRX

ng add @ngrx/store @ngrx/effects @ngrx/component

3. Crear accions

Aquí, crearem 4 accions que són necessàries per gestionar l’estat de l’aplicació de xat.

Fitxer : store/actions/actions.ts

import { createAction, props } from '@ngrx/store';

export const loadMessages = createAction('[Chat] Load Messages', props<{ channelId: string }>());
export const loadMessagesSuccess = createAction('[Chat] Load Messages Success', props<{ messages: any[] }>());

export const sendMessage = createAction('[Chat] Send Message', props<{ message }>());
export const addMessageToList = createAction('[Chat] Add Message To List', props<{ message }>());

4. Crear efectes

Els efectes ofereixen una manera d’interactuar amb aquests serveis i aïllar-los dels components.

Ús

Els efectes són útils, si voleu gestionar tasques com ara obtenir dades, tasques de llarga durada que produeixen diversos esdeveniments i altres interaccions externes.

Nota: per recordar, en la majoria dels escenaris, enviarà accions, però no és obligatori enviar sempre accions.

Per escriure efectes sense enviar les accions, passeu el segon paràmetre acreateEffect() funcions amb { dispatch: false }

Fitxer: state/effects/effects.ts

import { Actions, createEffect, ofType } from '@ngrx/effects';
import { Injectable } from '@angular/core';
import { map, switchMap } from 'rxjs/operators';
import * as chatActions from '../actions/actions';
import { from } from 'rxjs';
import { APIService } from '../../API.service';

@Injectable()
export class ChatEffects {

  constructor(
    private actions$: Actions,
    private api: APIService,
  ) { }

  /** Load the List of Messages */
  loadMessages$ = createEffect(() => this.actions$.pipe(
    ofType(chatActions.loadMessages),
    switchMap(({ channelId }) => {
      return from(this.api.MessagesByChannelId(channelId)).pipe(
        map((res: any) => {
          return chatActions.loadMessagesSuccess({ messages: res.items });
        }),
      );
    })
  ));

  /** Send message and call no actions */
  sendMessage$ = createEffect(() => this.actions$.pipe(
    ofType(chatActions.sendMessage),
    switchMap(({ message }) => {
      return from(this.api.CreateMessage(message));
    })
  ), { dispatch: false });
}

5. Crear reductors

Cada funció de reducció pren el més recentAction enviat, l’estat actual i determina si es retorna un estat recent modificat o l’estat original. Ara, en l’exemple següent us guiarem sobre com escriure funcions reductores, registreu-les al vostreStore , i compondre estats de característiques.

Fitxer: store/reducers/reducers.ts

import { Action, createReducer, on } from '@ngrx/store';
import * as chatActions from '../actions/actions';

export interface IChatState {
  messages: any[];
}

/** Initial State */
export const initialState: IChatState = {
  messages: [],
};

export function chatReducer(state: IChatState | undefined, action: Action): IChatState {
  return reducer(state, action);
}

const reducer = createReducer<IChatState>(
  initialState,

  /** Loaded Messafes */
  on(chatActions.loadMessagesSuccess, (state, { messages }) => ({
    ...state,
    messages
  })),

  /** Add message to the messages array */
  on(chatActions.addMessageToList, (state, { message }) => ({
    ...state,
    messages: [...state.messages, message]
  })),
);

6. Crear selectors

El selector que hem creat aquí retornarà l’ observable de tots els missatges

Fitxer: store/selectors/selectors.ts

import { createSelector } from '@ngrx/store';

export const selectChatState = (state) => state;

export const selectMessages = createSelector(
  selectChatState,
  (state) => state.chat.messages
);

7. Gestionar l’Estat

En aquesta secció, veurem quins són tots els esdeveniments on hem d’actualitzar l’estat:

  • Carregar l’aplicació
  • Enviament d’un missatge
  • Recepció d’un missatge

Fitxer: app.component.ts

import { Component, OnInit } from '@angular/core';
import { NavigationEnd, Router, RouterEvent } from '@angular/router';
import { select, Store } from '@ngrx/store';
import { Observable } from 'rxjs';
import { delay } from 'rxjs/operators';
import { APIService } from './API.service';
import { addMessageToList, loadMessages, sendMessage } from './store/actions/actions';
import { IChatState } from './store/reducers/reducer';
import { selectMessages } from './store/selectors/selectors';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
  title = 'amplify-chat-angular';
  username: string;
  messages: Observable<any[]>;

  constructor(
    private api: APIService,
    private router: Router,
    private store: Store<IChatState>
  ) { }

  ngOnInit(): void {
    this.router.events.subscribe((events: RouterEvent) => {
      if (events instanceof NavigationEnd) {
        const qParams = this.router.routerState.snapshot.root.queryParams;
        if (qParams && qParams.user) {
          this.username = qParams.user;
        } else {
          this.router.navigate(['/'], { queryParams: { user: 'Dave' } });
        }
      }
    });

    this.listMessages();
    this.onCreateMessage();
  }

  send(event, inputElement: HTMLInputElement): void {
    event.preventDefault();
    event.stopPropagation();
    const input = {
      channelID: '2',
      author: this.username.trim(),
      body: inputElement.value.trim()
    };

    this.store.dispatch(sendMessage({ message: input }));
    inputElement.value = '';
  }

  listMessages(): void {
    this.store.dispatch(loadMessages({ channelId: '2' }));
    this.messages = this.store.pipe(
      select(selectMessages),
      delay(10)
    );
  }

  onCreateMessage(): void {
    this.api.OnCreateMessageListener.subscribe(
      {
        next: (val: any) => {
          console.log(val);
          this.store.dispatch(addMessageToList({ message: val.value.data.onCreateMessage }));
        }
      }
    );
  }
}

Explicació

  • listMessages enviaments de mètodes loadMessages acció ambchannelId per recollir tots els missatges.
  • Quan l’usuari envia un missatge,sendMessage es crida l’acció i envia el missatge.
  • Quan l’usuari rep un missatge,addMessageToList s’envia l’acció i afegeix el missatgemessages llista

8. Crea una plantilla

En aquesta secció, farem servir,ngrxPush tub de@ngrx/component .

ElngrxPush la canonada serveix com a reemplaçament d’entrada de laasync canonada.

ngrxPush conté un maneig intel·ligent de la detecció de canvis que ens permetrà executar-nos en mode de zona plena i sense cap canvi al codi.

Ús:

ElngrxPush la canonada es proporciona a través delReactiveComponentModule . Per tant, per utilitzar-lo afegiu el ReactiveComponentModule fins alimports del vostre NgModule .

Fitxer : app.component.html

<div id="root">
  <div class="container">
    <div class="messages">
      <div class="messages-scroller">
        <ng-container *ngIf="messages$ | async as messages">
          <ng-container *ngFor="let message of messages">
            <div [ngClass]="message.author === username ? 'message me' : 'message'">
              {{message.body}}
            </div>
          </ng-container>
        </ng-container>
      </div>

    </div>
    <div class="chat-bar">
      <div class="form">
        <input #messageInput type="text" name="messageBody" placeholder="Type your message here" value="
          (keyup.enter)="send($event, messageInput)" />
      </div>
    </div>
  </div>
</div>

Això és tot, ara estem gestionant l’estat mitjançant NGRX.

T’ha agradat llegir això i t’agradaria aprendre més sobre angular i redux?, aquí hi ha un altre gran article, fes-hi una ullada!

Unimedia Technology

Aquí a Unimedia Technology tenim un equip de desenvolupadors angulars que poden desenvolupar els vostres taulers web i aplicacions web més difícils.

Recorda que a Unimedia som experts en tecnologies emergents, així que no dubtis a contactar amb nosaltres si necessites assessorament o serveis. Estarem encantats d’ajudar-te.

Unimedia Technology

El teu soci de desenvolupament de software

Som una consultoria tecnològica d’avantguarda especialitzada en arquitectura i desenvolupament de programari personalitzat.

Els nostres serveis

Registra't per rebre les nostres actualitzacions

Estigueu al dia, estigueu informat i donem forma junts al futur de la tecnologia!

Lectures relacionades

Aprofundeix amb aquests articles

Exploreu més coneixements experts d’Unimedia i anàlisis en profunditat en l’àmbit del desenvolupament de programari i la tecnologia.

Let’s make your vision a reality!

Simply fill out this form to begin your journey towards innovation and efficiency.

Fem realitat la teva visió!

Només has d’omplir aquest formulari per començar el teu viatge cap a la innovació i l’eficiència.