Ngrx ve Angular 2 Eğitimi: Reaktif Bir Uygulama Oluşturma
Yayınlanan: 2022-03-11Açısal alemde reaktif programlama hakkında çok konuşuyoruz. Reaktif programlama ve Angular 2 el ele gidiyor gibi görünüyor. Bununla birlikte, her iki teknolojiye de aşina olmayan biri için, bunların neyle ilgili olduğunu anlamak oldukça göz korkutucu bir görev olabilir.
Bu makalede, Ngrx kullanarak reaktif bir Angular 2 uygulaması oluşturarak, kalıbın ne olduğunu, kalıbın nerede yararlı olabileceğini ve kalıbın daha iyi Angular 2 uygulamaları oluşturmak için nasıl kullanılabileceğini öğreneceksiniz.
Ngrx, reaktif uzantılar için bir grup Angular kitaplığıdır. Ngrx/Store, Angular 2'nin iyi bilinen RxJS gözlemlenebilirlerini kullanarak Redux modelini uygular. Uygulama durumunuzu düz nesnelere basitleştirerek, tek yönlü veri akışını zorlayarak ve daha pek çok avantaj sağlar. Ngrx/Effects kitaplığı, uygulamanın yan etkileri tetikleyerek dış dünya ile iletişim kurmasını sağlar.
Reaktif Programlama Nedir?
Reaktif programlama, bugünlerde çokça duyduğunuz bir terimdir, ancak bu gerçekten ne anlama geliyor?
Reaktif programlama, uygulamaların uygulamalarınızdaki olayları ve veri akışını işleme şeklidir. Reaktif programlamada, bileşenlerinizi ve yazılımınızın diğer parçalarını, değişiklik istemek yerine bu değişikliklere tepki verecek şekilde tasarlarsınız. Bu harika bir değişim olabilir.
Bildiğiniz gibi, reaktif programlama için harika bir araç RxJS'dir.
Bu kitaplık, gelen verileri dönüştürmek için gözlemlenebilirler ve çok sayıda operatör sağlayarak, uygulamanızdaki olayları yönetmenize yardımcı olacaktır. Aslında, gözlemlenebilirlerle, olayı tek seferlik bir olay değil, bir olaylar akışı olarak görebilirsiniz. Bu, örneğin dinleyeceğiniz yeni bir etkinlik oluşturmak için bunları birleştirmenize olanak tanır.
Reaktif programlama, bir uygulamanın farklı bölümleri arasında iletişim kurma şeklinizde bir değişikliktir. Verileri doğrudan ihtiyaç duyulan bileşene veya hizmete göndermek yerine, reaktif programlamada veri değişikliklerine tepki veren bileşen veya hizmettir.
Ngrx hakkında bir kelime
Bu öğretici aracılığıyla oluşturacağınız uygulamayı anlamak için temel Redux kavramlarına hızlı bir dalış yapmalısınız.
Mağaza
Mağaza, müşteri tarafı veritabanınız olarak görülebilir, ancak daha da önemlisi, uygulamanızın durumunu yansıtır. Onu gerçeğin tek kaynağı olarak görebilirsiniz.
Redux modelini takip ettiğinizde değiştirdiğiniz ve ona eylemler göndererek değiştirdiğiniz tek şey budur.
redüktör
Redüktörler, belirli bir eylemle ne yapacağını ve uygulamanızın önceki durumunu bilen işlevlerdir.
Redüktörler mağazanızdan önceki durumu alacak ve ona saf bir fonksiyon uygulayacaktır. Pure, işlevin aynı girdi için her zaman aynı değeri döndürdüğü ve hiçbir yan etkisinin olmadığı anlamına gelir. Bu saf işlevin sonucundan, mağazanıza konacak yeni bir duruma sahip olacaksınız.
Hareketler
Eylemler, mağazanızı değiştirmek için gerekli bilgileri içeren yüklerdir. Temel olarak, bir eylemin, durumu değiştirmek için redüktör işlevinizin alacağı bir tür ve bir yük vardır.
sevk memuru
Göndericiler, eyleminizi göndermeniz için yalnızca bir giriş noktasıdır. Ngrx'te doğrudan mağaza üzerinde bir sevk yöntemi vardır.
ara katman yazılımı
Ara yazılım, bu makalede kullanmayacağınız halde yan etkiler oluşturmak için gönderilen her eylemi durduracak bazı işlevlerdir. Ngrx/Effect kitaplığında uygulanırlar ve gerçek dünya uygulamaları oluştururken onlara ihtiyaç duymanız için büyük bir şans vardır.
Ngrx'i Neden Kullanmalı?
karmaşıklık
Depolama ve tek yönlü veri akışı, uygulamanızın bölümleri arasındaki bağlantıyı büyük ölçüde azaltır. Bu azaltılmış bağlantı, uygulamanızın karmaşıklığını azaltır, çünkü her parça yalnızca belirli durumlarla ilgilenir.
Takım
Uygulamanızın tüm durumu tek bir yerde depolanır, bu nedenle uygulama durumunuzun genel bir görünümüne sahip olmak kolaydır ve geliştirme sırasında yardımcı olur. Ayrıca, Redux ile birlikte, mağazadan yararlanan ve örneğin uygulamanın belirli bir durumunu yeniden oluşturmaya veya zaman yolculuğu yapmaya yardımcı olabilecek birçok güzel geliştirme aracı gelir.
Mimari sadelik
Ngrx'in birçok faydası diğer çözümlerle elde edilebilir; Ne de olsa Redux bir mimari modeldir. Ancak, ortak düzenleme araçları gibi Redux modeline çok uygun bir uygulama oluşturmanız gerektiğinde, kalıbı izleyerek kolayca özellikler ekleyebilirsiniz.
Ne yaptığınızı düşünmek zorunda olmasanız da, gönderilen tüm eylemleri izleyebileceğiniz için tüm uygulamalarınıza analitik gibi bazı şeyler eklemek önemsiz hale gelir.
Küçük öğrenme eğrisi
Bu model çok yaygın olarak benimsendiği ve basit olduğu için ekibinizdeki yeni kişilerin yaptıklarınızı çabucak yakalaması gerçekten çok kolay.
Ngrx, bir izleme panosu gibi uygulamanızı değiştirebilecek çok sayıda harici aktörünüz olduğunda en çok parlar. Bu durumlarda uygulamanıza itilen tüm gelen verileri yönetmek zordur ve durum yönetimi zorlaşır. Bu yüzden onu değişmez bir durumla basitleştirmek istiyorsunuz ve bu, Ngrx mağazasının bize sağladığı bir şey.
Ngrx ile Uygulama Oluşturma
Ngrx'in gücü, uygulamamıza gerçek zamanlı olarak aktarılan dış verileriniz olduğunda en çok parlar. Bunu akılda tutarak, çevrimiçi serbest çalışanları gösteren ve onları filtrelemenize izin veren basit bir serbest çalışan ızgarası oluşturalım.
Projeyi Kurmak
Angular CLI, kurulum sürecini büyük ölçüde basitleştiren harika bir araçtır. Kullanmak istemeyebilirsiniz, ancak bu makalenin geri kalanının onu kullanacağını unutmayın.
npm install -g @angular/cli
Ardından, yeni bir uygulama oluşturmak ve tüm Ngrx kitaplıklarını kurmak istiyorsunuz:
ng new toptal-freelancers npm install ngrx --save
Serbest Çalışanlar Düşürücü
Redüktörler, Redux mimarisinin temel bir parçasıdır, bu yüzden uygulamayı oluştururken neden önce onlarla başlamıyorsunuz?
İlk olarak, mağazaya her eylem gönderildiğinde yeni durumumuzu oluşturmaktan sorumlu olacak bir "serbest çalışanlar" azaltıcı oluşturun.
freelancer-grid/freelancers.reducer.ts
import { Action } from '@ngrx/store'; export interface AppState { freelancers : Array<IFreelancer> } export interface IFreelancer { name: string, email: string, thumbnail: string } export const ACTIONS = { FREELANCERS_LOADED: 'FREELANCERS_LOADED', } export function freelancersReducer( state: Array<IFreelancer> = [], action: Action): Array<IFreelancer> { switch (action.type) { case ACTIONS.FREELANCERS_LOADED: // Return the new state with the payload as freelancers list return Array.prototype.concat(action.payload); default: return state; } }
İşte serbest çalışan redüktörümüz.
Bu işlev, mağaza aracılığıyla her eylem gönderildiğinde çağrılır. Eylem FREELANCERS_LOADED
ise, eylem yükünden yeni bir dizi oluşturacaktır. Değilse, eski durum referansını döndürür ve hiçbir şey eklenmez.
Burada, eski durum referansı döndürülürse, durumun değişmemiş olarak kabul edileceğini not etmek önemlidir. Bu, bir state.push(something)
, durumun değişmiş olarak kabul edilmeyeceği anlamına gelir. Redüktör işlevlerinizi yaparken bunu aklınızda bulundurun.
Devletler değişmez. Her değiştiğinde yeni bir durum döndürülmelidir.
Serbest Çalışan Izgara Bileşeni
Çevrimiçi serbest çalışanlarımıza göstermek için bir ızgara bileşeni oluşturun. İlk başta, sadece mağazada olanı yansıtacaktır.
ng generate component freelancer-grid
Aşağıdakileri freelancer-grid.component.ts içine koyun
import { Component, OnInit } from '@angular/core'; import { Store } from '@ngrx/store'; import { AppState, IFreelancer, ACTIONS } from './freelancer-reducer'; import * as Rx from 'RxJS'; @Component({ selector: 'app-freelancer-grid', templateUrl: './freelancer-grid.component.html', styleUrls: ['./freelancer-grid.component.scss'], }) export class FreelancerGridComponent implements OnInit { public freelancers: Rx.Observable<Array<IFreelancer>>; constructor(private store: Store<AppState>) { this.freelancers = store.select('freelancers'); } }
Ve freelancer-grid.component.html dosyasında aşağıdakiler:
<span class="count">Number of freelancers online: {{(freelancers | async).length}}</span> <div class="freelancer fade thumbail" *ngFor="let freelancer of freelancers | async"> <button type="button" class="close" aria-label="Close" (click)="delete(freelancer)"><span aria-hidden="true">×</span></button><br> <img class="img-circle center-block" src="{{freelancer.thumbnail}}" /><br> <div class="info"><span><strong>Name: </strong>{{freelancer.name}}</span> <span><strong>Email: </strong>{{freelancer.email}}</span></div> <a class="btn btn-default">Hire {{freelancer.name}}</a> </div>
Peki az önce ne yaptın?
İlk olarak, freelancer-grid
adında yeni bir bileşen oluşturdunuz.
Bileşen, Ngrx deposunda bulunan uygulama durumunun bir parçası olan freelancers
adlı bir özellik içerir. Seçme operatörünü kullanarak, genel uygulama durumu hakkında yalnızca freelancers
özelliği tarafından bilgilendirilmeyi seçersiniz. Böylece, uygulama durumunun freelancers
özelliği her değiştiğinde, gözlemlenebiliriniz bilgilendirilecektir.
Bu çözümün güzel yanlarından biri, bileşeninizin yalnızca bir bağımlılığa sahip olması ve bileşeninizi çok daha az karmaşık ve kolayca yeniden kullanılabilir hale getirenin mağaza olmasıdır.
Şablon kısmında, çok karmaşık bir şey yapmadınız. *ngFor
içinde zaman uyumsuz boru kullanımına dikkat edin. Gözlemlenebilir freelancers
doğrudan yinelenebilir değildir, ancak Angular sayesinde, async borusunu kullanarak paketi açmak ve dom'u değerine bağlamak için araçlara sahibiz. Bu, gözlemlenebilir olanla çalışmayı çok daha kolay hale getirir.
Serbest Çalışanları Kaldır İşlevini Ekleme
Artık işlevsel bir temele sahip olduğunuza göre, uygulamaya bazı eylemler ekleyelim.
Bir serbest çalışanı eyaletten çıkarmak istiyorsunuz. Redux'un nasıl çalıştığına göre, önce o eylemi ondan etkilenen her durumda tanımlamanız gerekir.
Bu durumda, yalnızca freelancers
azaltıcıdır:
export const ACTIONS = { FREELANCERS_LOADED: 'FREELANCERS_LOADED', DELETE_FREELANCER: 'DELETE_FREELANCER', } export function freelancersReducer( state: Array<IFreelancer> = [], action: Action): Array<IFreelancer> { switch (action.type) { case ACTIONS.FREELANCERS_LOADED: // Return the new state with the payload as freelancers list return Array.prototype.concat(action.payload); case ACTIONS.DELETE_FREELANCER: // Remove the element from the array state.splice(state.indexOf(action.payload), 1); // We need to create another reference return Array.prototype.concat(state); default: return state; } }
Burada yeni bir değişmez duruma sahip olmak için eskisinden yeni bir dizi oluşturmak gerçekten önemlidir.
Artık bileşeninize bu eylemi mağazaya gönderecek bir serbest çalışanları sil işlevi ekleyebilirsiniz:
delete(freelancer) { this.store.dispatch({ type: ACTIONS.DELETE_FREELANCER, payload: freelancer, }) }
Bu basit görünmüyor mu?
Artık belirli bir serbest çalışanı eyaletten kaldırabilirsiniz ve bu değişiklik uygulamanız aracılığıyla yayılacaktır.

Şimdi, mağaza aracılığıyla birbirleriyle nasıl etkileşime girebileceklerini görmek için uygulamaya başka bir bileşen eklerseniz ne olur?
Filtre Redüktörü
Her zaman olduğu gibi, redüktörle başlayalım. Bu bileşen için oldukça basittir. Redüktörün her zaman yalnızca bizim gönderdiğimiz özellik ile yeni bir durum döndürmesini istiyorsunuz. Şöyle görünmelidir:
import { Action } from '@ngrx/store'; export interface IFilter { name: string, email: string, } export const ACTIONS = { UPDATE_FITLER: 'UPDATE_FITLER', CLEAR_FITLER: 'CLEAR_FITLER', } const initialState = { name: '', email: '' }; export function filterReducer( state: IFilter = initialState, action: Action): IFilter { switch (action.type) { case ACTIONS.UPDATE_FITLER: // Create a new state from payload return Object.assign({}, action.payload); case ACTIONS.CLEAR_FITLER: // Create a new state from initial state return Object.assign({}, initialState); default: return state; } }
Filtre Bileşeni
import { Component, OnInit } from '@angular/core'; import { IFilter, ACTIONS as FilterACTIONS } from './filter-reducer'; import { Store } from '@ngrx/store'; import { FormGroup, FormControl } from '@angular/forms'; import * as Rx from 'RxJS'; @Component({ selector: 'app-filter', template: '<form class="filter">'+ '<label>Name</label>'+ '<input type="text" [formControl]="name" name="name"/>'+ '<label>Email</label>'+ '<input type="text" [formControl]="email" name="email"/>'+ '<a (click)="clearFilter()" class="btn btn-default">Clear Filter</a>'+ '</form>', styleUrls: ['./filter.component.scss'], }) export class FilterComponent implements OnInit { public name = new FormControl(); public email = new FormControl(); constructor(private store: Store<any>) { store.select('filter').subscribe((filter: IFilter) => { this.name.setValue(filter.name); this.email.setValue(filter.email); }) Rx.Observable.merge(this.name.valueChanges, this.email.valueChanges).debounceTime(1000).subscribe(() => this.filter()); } ngOnInit() { } filter() { this.store.dispatch({ type: FilterACTIONS.UPDATE_FITLER, payload: { name: this.name.value, email: this.email.value, } }); } clearFilter() { this.store.dispatch({ type: FilterACTIONS.CLEAR_FITLER, }) } }
İlk olarak, durumumuzu yansıtan iki alanlı (isim ve e-posta) bir form içeren basit bir şablon yaptınız.
Bu alanları devletle senkronize halde tutuyorsunuz, freelancers
durumuyla yaptığınızdan biraz farklı. Aslında, gördüğünüz gibi, filtre durumuna abone oldunuz ve her seferinde, formControl
yeni bir değer atamanızı tetikliyor.
Angular 2'nin güzel yanlarından biri, size gözlemlenebilirlerle etkileşimde bulunmanız için birçok araç sağlamasıdır.
Zaman uyumsuz boruyu daha önce gördünüz ve şimdi bir girdinin değeri üzerinde gözlemlenebilir olmanızı sağlayan formControl
sınıfını görüyorsunuz. Bu, filtre bileşeninde yaptığınız gibi süslü şeylere izin verir.
Gördüğünüz gibi, formControls tarafından verilen iki gözlemlenebiliri birleştirmek için Rx.observable.merge
kullanırsınız ve ardından filter
işlevini tetiklemeden önce bu yeni gözlemlenebilirliği formControls
.
Daha basit bir deyişle, formControl
adının veya e-posta adresinin değişmesinden sonra bir saniye bekler ve ardından filter
işlevini çağırırsınız.
Bu harika değil mi?
Bütün bunlar birkaç kod satırında yapılır. RxJS'yi sevmenizin nedenlerinden biri de budur. Aksi takdirde daha karmaşık olan bu süslü şeylerin çoğunu kolayca yapmanızı sağlar.
Şimdi bu filtre işlevine geçelim. Bu ne işe yarıyor?
UPDATE_FILTER
eylemini ad ve e-posta değeriyle birlikte gönderir ve redüktör, durumu bu bilgilerle değiştirmeyle ilgilenir.
Daha ilginç bir şeye geçelim.
Bu filtreyi daha önce oluşturduğunuz serbest çalışan ızgaranızla nasıl etkileşime sokarsınız?
Basit. Size sadece mağazanın filtre kısmını dinlemek kalıyor. Kodun nasıl göründüğüne bir bakalım.
import { Component, OnInit } from '@angular/core'; import { Store } from '@ngrx/store'; import { AppState, IFreelancer, ACTIONS } from './freelancer-reducer'; import { IFilter, ACTIONS as FilterACTIONS } from './../filter/filter-reducer'; import * as Rx from 'RxJS'; @Component({ selector: 'app-freelancer-grid', templateUrl: './freelancer-grid.component', styleUrls: ['./freelancer-grid.component.scss'], }) export class FreelancerGridComponent implements OnInit { public freelancers: Rx.Observable<Array<IFreelancer>>; public filter: Rx.Observable<IFilter>; constructor(private store: Store<AppState>) { this.freelancers = Rx.Observable.combineLatest(store.select('freelancers'), store.select('filter'), this.applyFilter); } applyFilter(freelancers: Array<IFreelancer>, filter: IFilter): Array<IFreelancer> { return freelancers .filter(x => !filter.name || x.name.toLowerCase().indexOf(filter.name.toLowerCase()) !== -1) .filter(x => !filter.email || x.email.toLowerCase().indexOf(filter.email.toLowerCase()) !== -1) } ngOnInit() { } delete(freelancer) { this.store.dispatch({ type: ACTIONS.DELETE_FREELANCER, payload: freelancer, }) } }
Bundan daha karmaşık değil.
Bir kez daha, filtre ve serbest çalışanlar durumunu birleştirmek için RxJS'nin gücünü kullandınız.
Aslında, iki gözlemlenebilirden biri ateşlenirse, combineLatest
ve ardından applyFilter
işlevini kullanarak her durumu birleştirir. Bunu yapan yeni bir gözlemlenebilir döndürür. Diğer kod satırlarını değiştirmek zorunda değiliz.
Bileşenin, filtrenin nasıl elde edildiği, değiştirildiği veya saklandığı ile ilgilenmediğine dikkat edin; başka herhangi bir devlet için yapacağı gibi sadece onu dinler. Filtre işlevini yeni ekledik ve yeni bağımlılıklar eklemedik.
Parlatmak
Gerçek zamanlı verilerle uğraşmak zorunda kaldığımızda Ngrx kullanımının gerçekten parladığını hatırlıyor musunuz? O kısmı uygulamamıza ekleyelim bakalım nasıl olacak.
freelancers-service
.
ng generate service freelancer
Serbest çalışan hizmeti, veriler üzerinde gerçek zamanlı işlemi simüle edecek ve şöyle görünmelidir.
import { Injectable } from '@angular/core'; import { Store } from '@ngrx/store'; import { AppState, IFreelancer, ACTIONS } from './freelancer-grid/freelancer-reducer'; import { Http, Response } from '@angular/http'; @Injectable() export class RealtimeFreelancersService { private USER_API_URL = 'https://randomuser.me/api/?results=' constructor(private store: Store<AppState>, private http: Http) { } private toFreelancer(value: any) { return { name: value.name.first + ' ' + value.name.last, email: value.email, thumbail: value.picture.large, } } private random(y) { return Math.floor(Math.random() * y); } public run() { this.http.get(`${this.USER_API_URL}51`).subscribe((response) => { this.store.dispatch({ type: ACTIONS.FREELANCERS_LOADED, payload: response.json().results.map(this.toFreelancer) }) }) setInterval(() => { this.store.select('freelancers').first().subscribe((freelancers: Array<IFreelancer>) => { let getDeletedIndex = () => { return this.random(freelancers.length - 1) } this.http.get(`${this.USER_API_URL}${this.random(10)}`).subscribe((response) => { this.store.dispatch({ type: ACTIONS.INCOMMING_DATA, payload: { ADD: response.json().results.map(this.toFreelancer), DELETE: new Array(this.random(6)).fill(0).map(() => getDeletedIndex()), } }); this.addFadeClassToNewElements(); }); }); }, 10000); } private addFadeClassToNewElements() { let elements = window.document.getElementsByClassName('freelancer'); for (let i = 0; i < elements.length; i++) { if (elements.item(i).className.indexOf('fade') === -1) { elements.item(i).classList.add('fade'); } } } }
Bu hizmet mükemmel değil, ancak yaptığı şeyi yapıyor ve demo amacıyla birkaç şeyi göstermemize izin veriyor.
İlk olarak, bu hizmet oldukça basittir. Bir kullanıcı API'sini sorgular ve sonuçları mağazaya gönderir. Bu çok kolay ve verilerin nereye gittiğini düşünmek zorunda değilsiniz. Mağazaya gidiyor, bu Redux'u aynı anda hem çok kullanışlı hem de tehlikeli yapan bir şey - ama buna daha sonra geri döneceğiz. Her on saniyede bir, hizmet birkaç serbest çalışan seçer ve bunları silmek için bir işlemle birlikte birkaç diğer serbest çalışana bir işlem gönderir.
Redüktörümüzün bununla başa çıkabilmesini istiyorsak, onu değiştirmemiz gerekir:
import { Action } from '@ngrx/store'; export interface AppState { freelancers : Array<IFreelancer> } export interface IFreelancer { name: string, email: string, } export const ACTIONS = { LOAD_FREELANCERS: 'LOAD_FREELANCERS', INCOMMING_DATA: 'INCOMMING_DATA', DELETE_FREELANCER: 'DELETE_FREELANCER', } export function freelancersReducer( state: Array<IFreelancer> = [], action: Action): Array<IFreelancer> { switch (action.type) { case ACTIONS.INCOMMING_DATA: action.payload.DELETE.forEach((index) => { state.splice(state.indexOf(action.payload), 1); }) return Array.prototype.concat(action.payload.ADD, state); case ACTIONS.FREELANCERS_LOADED: // Return the new state with the payload as freelancers list return Array.prototype.concat(action.payload); case ACTIONS.DELETE_FREELANCER: // Remove the element from the array state.splice(state.indexOf(action.payload), 1); // We need to create another reference return Array.prototype.concat(state); default: return state; } }
Artık bu tür işlemleri halledebiliyoruz.
Bu hizmette gösterilen bir şey, tüm durum değişiklikleri sürecinin eşzamanlı olarak yapılmasının, bunun fark edilmesinin oldukça önemli olduğudur. Durumun uygulaması eşzamansızsa, this.addFadeClassToNewElements();
bu işlev çağrıldığında DOM öğesi oluşturulmayacağından çalışmaz.
Şahsen, tahmin edilebilirliği geliştirdiği için bunu oldukça faydalı buluyorum.
Bina Uygulamaları, Reaktif Yol
Bu öğretici aracılığıyla Ngrx, RxJS ve Angular 2 kullanarak reaktif bir uygulama oluşturdunuz.
Gördüğünüz gibi, bunlar güçlü araçlar. Burada inşa ettiğiniz şey bir Redux mimarisinin uygulaması olarak da görülebilir ve Redux kendi içinde güçlüdür. Bununla birlikte, bazı kısıtlamaları da vardır. Ngrx kullanırken, bu kısıtlamalar kaçınılmaz olarak uygulamamızın kullandığımız kısmına yansır.
Yukarıdaki şema, az önce yaptığınız mimarinin kaba bir halidir.
Bazı bileşenler birbirini etkiliyor olsa bile birbirlerinden bağımsız olduklarını fark edebilirsiniz. Bu, bu mimarinin bir özelliğidir: Bileşenler, mağaza olan ortak bir bağımlılığı paylaşır.
Bu mimariyle ilgili bir başka özel şey de, işlevleri çağırmamamız, ancak eylemleri göndermemizdir. Ngrx'e bir alternatif, yalnızca uygulamalarınızın gözlemlenebilirleri ile belirli bir durumu yöneten bir hizmet yapmak ve eylemler yerine o hizmetteki işlevleri çağırmak olabilir. Bu şekilde, sorunlu devleti izole ederken devletin merkezileşmesini ve tepkiselliğini elde edebilirsiniz. Bu yaklaşım, bir indirgeyici oluşturma ek yükünü azaltmanıza ve eylemleri düz nesneler olarak tanımlamanıza yardımcı olabilir.
Uygulamanızın durumunun farklı kaynaklardan güncellendiğini ve karmakarışık olmaya başladığını hissettiğinizde, ihtiyacınız olan şey Ngrx'tir.