Tutorial Ngrx dan Angular 2: Membangun Aplikasi Reaktif

Diterbitkan: 2022-03-11

Kami berbicara banyak tentang pemrograman reaktif di ranah Angular. Pemrograman reaktif dan Angular 2 tampaknya berjalan seiring. Namun, bagi siapa pun yang tidak terbiasa dengan kedua teknologi, itu bisa menjadi tugas yang menakutkan untuk mengetahui apa itu semua.

Dalam artikel ini, melalui membangun aplikasi Angular 2 reaktif menggunakan Ngrx, Anda akan mempelajari apa itu pola, di mana pola itu terbukti berguna, dan bagaimana pola dapat digunakan untuk membangun aplikasi Angular 2 yang lebih baik.

Ngrx adalah sekelompok perpustakaan Angular untuk ekstensi reaktif. Ngrx/Store mengimplementasikan pola Redux menggunakan observables RxJS yang terkenal dari Angular 2. Ini memberikan beberapa keuntungan dengan menyederhanakan status aplikasi Anda ke objek biasa, menegakkan aliran data searah, dan banyak lagi. Pustaka Ngrx/Effects memungkinkan aplikasi untuk berkomunikasi dengan dunia luar dengan memicu efek samping.

Apa itu Pemrograman Reaktif?

Pemrograman reaktif adalah istilah yang sering Anda dengar akhir-akhir ini, tetapi apa artinya sebenarnya?

Pemrograman reaktif adalah cara aplikasi menangani peristiwa dan aliran data dalam aplikasi Anda. Dalam pemrograman reaktif, Anda mendesain komponen Anda dan bagian lain dari perangkat lunak Anda untuk bereaksi terhadap perubahan tersebut alih-alih meminta perubahan. Ini bisa menjadi perubahan besar.

Alat hebat untuk pemrograman reaktif, seperti yang mungkin Anda ketahui, adalah RxJS.

Dengan menyediakan observables dan banyak operator untuk mengubah data yang masuk, library ini akan membantu Anda menangani event di aplikasi Anda. Bahkan, dengan observables, Anda dapat melihat acara sebagai aliran peristiwa dan bukan peristiwa satu kali. Ini memungkinkan Anda untuk menggabungkannya, misalnya, untuk membuat acara baru yang akan Anda dengarkan.

Pemrograman reaktif adalah perubahan cara Anda berkomunikasi di antara berbagai bagian aplikasi. Alih-alih mendorong data langsung ke komponen atau layanan yang membutuhkannya, dalam pemrograman reaktif, komponen atau layananlah yang bereaksi terhadap perubahan data.

Sepatah Kata tentang Ngrx

Untuk memahami aplikasi yang akan Anda buat melalui tutorial ini, Anda harus menyelami konsep inti Redux dengan cepat.

Toko

Toko dapat dilihat sebagai basis data sisi klien Anda tetapi, yang lebih penting, ini mencerminkan keadaan aplikasi Anda. Anda dapat melihatnya sebagai satu-satunya sumber kebenaran.

Ini adalah satu-satunya hal yang Anda ubah ketika Anda mengikuti pola Redux dan Anda memodifikasi dengan mengirimkan tindakan ke sana.

Peredam

Reducer adalah fungsi yang mengetahui apa yang harus dilakukan dengan tindakan tertentu dan status aplikasi Anda sebelumnya.

Pereduksi akan mengambil status sebelumnya dari toko Anda dan menerapkan fungsi murni padanya. Murni berarti bahwa fungsi selalu mengembalikan nilai yang sama untuk input yang sama dan tidak memiliki efek samping. Dari hasil fungsi murni itu, Anda akan memiliki status baru yang akan dimasukkan ke dalam toko Anda.

tindakan

Tindakan adalah muatan yang berisi informasi yang diperlukan untuk mengubah toko Anda. Pada dasarnya, suatu tindakan memiliki jenis dan muatan yang akan diambil oleh fungsi peredam Anda untuk mengubah status.

pengirim

Dispatcher hanyalah titik masuk bagi Anda untuk mengirimkan tindakan Anda. Di Ngrx, ada metode pengiriman langsung di toko.

perangkat tengah

Middleware adalah beberapa fungsi yang akan mencegat setiap tindakan yang sedang dikirim untuk menciptakan efek samping, meskipun Anda tidak akan menggunakannya dalam artikel ini. Mereka diimplementasikan di perpustakaan Ngrx/Effect, dan ada kemungkinan besar Anda akan membutuhkannya saat membangun aplikasi dunia nyata.

Mengapa Menggunakan Ngrx?

Kompleksitas

Penyimpanan dan aliran data searah sangat mengurangi sambungan antar bagian aplikasi Anda. Pengurangan kopling ini mengurangi kerumitan aplikasi Anda, karena setiap bagian hanya peduli dengan status tertentu.

Perkakas

Seluruh status aplikasi Anda disimpan di satu tempat, sehingga mudah untuk memiliki pandangan global tentang status aplikasi Anda dan membantu selama pengembangan. Juga, dengan Redux hadir banyak alat pengembang bagus yang memanfaatkan toko dan dapat membantu mereproduksi keadaan aplikasi tertentu atau melakukan perjalanan waktu, misalnya.

Kesederhanaan arsitektur

Banyak manfaat Ngrx dapat dicapai dengan solusi lain; lagi pula, Redux adalah pola arsitektur. Tetapi ketika Anda harus membangun aplikasi yang sangat cocok untuk pola Redux, seperti alat pengeditan kolaboratif, Anda dapat dengan mudah menambahkan fitur dengan mengikuti polanya.

Meskipun Anda tidak perlu memikirkan apa yang Anda lakukan, menambahkan beberapa hal seperti analitik melalui semua aplikasi Anda menjadi sepele karena Anda dapat melacak semua tindakan yang dikirim.

Kurva belajar kecil

Karena pola ini diadopsi secara luas dan sederhana, sangat mudah bagi orang-orang baru di tim Anda untuk mengejar apa yang Anda lakukan dengan cepat.

Ngrx paling bersinar saat Anda memiliki banyak aktor eksternal yang dapat memodifikasi aplikasi Anda, seperti dasbor pemantauan. Dalam kasus tersebut, sulit untuk mengelola semua data masuk yang didorong ke aplikasi Anda, dan pengelolaan status menjadi sulit. Itulah mengapa Anda ingin menyederhanakannya dengan status yang tidak dapat diubah, dan ini adalah satu hal yang disediakan oleh toko Ngrx kepada kami.

Membangun Aplikasi dengan Ngrx

Kekuatan Ngrx paling bersinar ketika Anda memiliki data luar yang didorong ke aplikasi kami secara real time. Dengan mengingat hal itu, mari buat kisi pekerja lepas sederhana yang menunjukkan pekerja lepas online dan memungkinkan Anda untuk memfilternya.

Menyiapkan Proyek

Angular CLI adalah alat luar biasa yang sangat menyederhanakan proses penyiapan. Anda mungkin ingin tidak menggunakannya tetapi perlu diingat bahwa sisa artikel ini akan menggunakannya.

 npm install -g @angular/cli

Selanjutnya, Anda ingin membuat aplikasi baru dan menginstal semua pustaka Ngrx:

 ng new toptal-freelancers npm install ngrx --save

Pengurang Freelancer

Reducer adalah bagian inti dari arsitektur Redux, jadi mengapa tidak memulainya terlebih dahulu saat membangun aplikasi?

Pertama, buat peredam "freelancer" yang akan bertanggung jawab untuk membuat status baru kami setiap kali tindakan dikirim ke toko.

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; } }

Jadi inilah peredam freelancer kami.

Fungsi ini akan dipanggil setiap kali tindakan dikirim melalui toko. Jika aksinya FREELANCERS_LOADED , itu akan membuat larik baru dari payload aksi. Jika tidak, itu akan mengembalikan referensi status lama dan tidak ada yang akan ditambahkan.

Penting untuk dicatat di sini bahwa, jika referensi status lama dikembalikan, status akan dianggap tidak berubah. Ini berarti jika Anda memanggil state.push(something) , status tidak akan dianggap telah berubah. Ingatlah hal itu saat melakukan fungsi peredam Anda.

Negara bagian tidak dapat diubah. Status baru harus dikembalikan setiap kali berubah.

Komponen Grid Freelancer

Buat komponen kisi untuk menampilkan freelancer online kami. Pada awalnya, itu hanya akan mencerminkan apa yang ada di toko.

 ng generate component freelancer-grid

Letakkan yang berikut ini di freelancer-grid.component.ts

 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'); } }

Dan berikut ini di freelancer-grid.component.html :

 <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">&times;</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>

Jadi apa yang baru saja Anda lakukan?

Pertama, Anda telah membuat komponen baru bernama freelancer-grid .

Komponen tersebut berisi properti bernama freelancers yang merupakan bagian dari status aplikasi yang terdapat di toko Ngrx. Dengan menggunakan operator pilih, Anda memilih untuk hanya diberi tahu oleh properti freelancers tentang status aplikasi secara keseluruhan. Jadi sekarang setiap kali properti freelancers dari status aplikasi berubah, observable Anda akan diberi tahu.

Satu hal yang indah dengan solusi ini adalah bahwa komponen Anda hanya memiliki satu ketergantungan, dan tokolah yang membuat komponen Anda jauh lebih kompleks dan mudah digunakan kembali.

Pada bagian template, Anda tidak melakukan hal yang terlalu rumit. Perhatikan penggunaan pipa async di *ngFor . Pekerja freelancers yang dapat diamati tidak dapat diubah secara langsung, tetapi berkat Angular, kami memiliki alat untuk membukanya dan mengikat dom ke nilainya dengan menggunakan pipa async. Ini membuat bekerja dengan yang dapat diamati jauh lebih mudah.

Menambahkan Fungsionalitas Hapus Freelancer

Sekarang setelah Anda memiliki basis fungsional, mari tambahkan beberapa tindakan ke aplikasi.

Anda ingin dapat menghapus pekerja lepas dari negara bagian. Menurut cara kerja Redux, Anda harus terlebih dahulu menentukan tindakan itu di setiap status yang terpengaruh olehnya.

Dalam hal ini, hanya peredam freelancers :

 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; } }

Sangat penting di sini untuk membuat array baru dari yang lama agar memiliki status baru yang tidak dapat diubah.

Sekarang, Anda dapat menambahkan fungsi hapus freelancer ke komponen Anda yang akan mengirimkan tindakan ini ke toko:

 delete(freelancer) { this.store.dispatch({ type: ACTIONS.DELETE_FREELANCER, payload: freelancer, }) }

Bukankah itu terlihat sederhana?

Anda sekarang dapat menghapus pekerja lepas tertentu dari status, dan perubahan itu akan menyebar melalui aplikasi Anda.

Sekarang bagaimana jika Anda menambahkan komponen lain ke aplikasi untuk melihat bagaimana mereka dapat berinteraksi satu sama lain melalui toko?

Peredam Filter

Seperti biasa, mari kita mulai dengan peredam. Untuk komponen itu, cukup sederhana. Anda ingin peredam selalu mengembalikan status baru hanya dengan properti yang kami kirim. Seharusnya terlihat seperti ini:

 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; } }

Komponen Filter

 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, }) } }

Pertama, Anda telah membuat template sederhana yang menyertakan formulir dengan dua bidang (nama dan email) yang mencerminkan status kita.

Anda menjaga agar bidang tersebut tetap sinkron dengan status sedikit berbeda dari apa yang Anda lakukan dengan status freelancers . Faktanya, seperti yang Anda lihat, Anda berlangganan status filter, dan setiap kali, itu memicu Anda menetapkan nilai baru ke formControl .

Satu hal yang bagus dengan Angular 2 adalah ia memberi Anda banyak alat untuk berinteraksi dengan yang dapat diamati.

Anda telah melihat pipa async sebelumnya, dan sekarang Anda melihat kelas formControl yang memungkinkan Anda memiliki nilai input yang dapat diamati. Ini memungkinkan hal-hal mewah seperti yang Anda lakukan di komponen filter.

Seperti yang Anda lihat, Anda menggunakan Rx.observable.merge untuk menggabungkan dua observable yang diberikan oleh formControls Anda, dan kemudian Anda mendebounce observable baru itu sebelum memicu fungsi filter .

Dengan kata yang lebih sederhana, Anda menunggu satu detik setelah salah satu nama atau formControl email telah berubah dan kemudian memanggil fungsi filter .

Bukankah itu luar biasa?

Semua itu dilakukan dalam beberapa baris kode. Ini adalah salah satu alasan mengapa Anda akan menyukai RxJS. Ini memungkinkan Anda untuk melakukan banyak hal mewah dengan mudah yang akan lebih rumit jika tidak.

Sekarang mari kita melangkah ke fungsi filter itu. Apa fungsinya?

Itu hanya mengirimkan tindakan UPDATE_FILTER dengan nilai nama dan email, dan peredam menangani perubahan status dengan informasi itu.

Mari kita beralih ke sesuatu yang lebih menarik.

Bagaimana Anda membuat filter itu berinteraksi dengan kisi freelancer yang Anda buat sebelumnya?

Sederhana. Anda hanya perlu mendengarkan bagian filter dari toko. Mari kita lihat seperti apa kodenya.

 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, }) } }

Hal ini tidak lebih rumit dari itu.

Sekali lagi, Anda menggunakan kekuatan RxJS untuk menggabungkan status filter dan freelancer.

Faktanya, combineLatest akan diaktifkan jika salah satu dari dua yang dapat diamati diaktifkan dan kemudian menggabungkan setiap status menggunakan fungsi applyFilter . Ini mengembalikan observable baru yang melakukannya. Kami tidak perlu mengubah baris kode lainnya.

Perhatikan bagaimana komponen tidak peduli tentang bagaimana filter diperoleh, dimodifikasi, atau disimpan; itu hanya mendengarkannya seperti yang akan dilakukannya untuk negara bagian lain mana pun. Kami baru saja menambahkan fungsionalitas filter dan kami tidak menambahkan dependensi baru.

Membuatnya Bersinar

Ingat bahwa penggunaan Ngrx benar-benar bersinar ketika kita harus berurusan dengan data waktu nyata? Mari tambahkan bagian itu ke aplikasi kita dan lihat bagaimana kelanjutannya.

Memperkenalkan layanan freelancers-service .

 ng generate service freelancer

Layanan freelancer akan mensimulasikan operasi waktu nyata pada data dan akan terlihat seperti ini.

 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'); } } } }

Layanan ini tidak sempurna, tetapi melakukan apa yang dilakukannya dan, untuk tujuan demo, ini memungkinkan kami untuk mendemonstrasikan beberapa hal.

Pertama, layanan ini cukup sederhana. Ini menanyakan API pengguna dan mendorong hasilnya ke toko. Ini tidak perlu dipikirkan lagi, dan Anda tidak perlu memikirkan kemana data itu pergi. Itu pergi ke toko, yang merupakan sesuatu yang membuat Redux sangat berguna dan berbahaya pada saat yang sama — tetapi kita akan kembali lagi nanti. Setelah setiap sepuluh detik, layanan memilih beberapa pekerja lepas dan mengirimkan operasi untuk menghapusnya bersama dengan operasi ke beberapa pekerja lepas lainnya.

Jika kita ingin peredam kita dapat menanganinya, kita perlu memodifikasinya:

 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; } }

Sekarang kami dapat menangani operasi semacam itu.

Satu hal yang ditunjukkan dalam layanan itu adalah, dari semua proses perubahan status yang dilakukan secara serempak, cukup penting untuk diperhatikan. Jika penerapan status asinkron, panggil this.addFadeClassToNewElements(); tidak akan berfungsi karena elemen DOM tidak akan dibuat saat fungsi ini dipanggil.

Secara pribadi, saya menemukan itu cukup berguna, karena meningkatkan prediktabilitas.

Membangun Aplikasi, Cara Reaktif

Melalui tutorial ini, Anda telah membangun aplikasi reaktif menggunakan Ngrx, RxJS, dan Angular 2.

Seperti yang Anda lihat, ini adalah alat yang ampuh. Apa yang telah Anda bangun di sini juga dapat dilihat sebagai implementasi arsitektur Redux, dan Redux itu sendiri sangat kuat. Namun, itu juga memiliki beberapa kendala. Saat kami menggunakan Ngrx, kendala itu pasti tercermin di bagian aplikasi yang kami gunakan.

Paradigma Reaktif

Diagram di atas adalah gambaran kasar dari arsitektur yang baru saja Anda buat.

Anda mungkin memperhatikan bahwa meskipun beberapa komponen saling mempengaruhi, mereka tidak tergantung satu sama lain. Ini adalah kekhasan arsitektur ini: Komponen berbagi ketergantungan yang sama, yang merupakan toko.

Hal khusus lainnya tentang arsitektur ini adalah bahwa kami tidak memanggil fungsi tetapi mengirimkan tindakan. Alternatif untuk Ngrx adalah dengan hanya membuat layanan yang mengelola status tertentu dengan aplikasi Anda yang dapat diamati dan fungsi panggilan pada layanan itu alih-alih tindakan. Dengan cara ini, Anda bisa mendapatkan sentralisasi dan reaktivitas keadaan sambil mengisolasi keadaan bermasalah. Pendekatan ini dapat membantu Anda mengurangi biaya pembuatan peredam dan menggambarkan tindakan sebagai objek biasa.

Ketika Anda merasa status aplikasi Anda sedang diperbarui dari berbagai sumber dan mulai berantakan, Ngrx adalah yang Anda butuhkan.

Terkait: Semua Perks, Tanpa Kerumitan: Tutorial Sudut 9