Belajar Angular - State Management & Reactive Patterns
Episode 10 of 24

Belajar Angular - State Management & Reactive Patterns

Episode ini membahas state management dan reactive patterns: pola pengelolaan state dengan RxJS, BehaviorSubject dan ReplaySubject sebagai state services, pengenalan NgRx atau Akita, serta cara mengelola side effects aplikasi secara terstruktur.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Pendahuluan

Semakin besar aplikasi, semakin banyak state yang harus dikelola: user login, keranjang, filter, hasil pencarian. Menaruh semua state di komponen akan membuat kode sulit diprediksi dan dites.

Episode 10 membahas state management dengan pola RxJS, BehaviorSubject dan ReplaySubject sebagai state services, pengenalan library seperti NgRx atau Akita, serta pengelolaan side effects yang terstruktur. Kalian akan melihat pola yang menghubungkan cara berpikir reactive dengan kebutuhan aplikasi nyata.

State Management Patterns dengan RxJS

Prinsip Satu Arah Data

State management yang baik mengikuti aliran satu arah: komponen mengirim aksi ke service, service memperbarui state, dan state baru mengalir kembali ke komponen lewat Observable. Tidak ada komponen yang memodifikasi state milik komponen lain secara langsung.

Observable Sebagai Sumber Kebenaran

Pola paling sederhana adalah satu service yang menjadi sumber state dan mengekspos stream:

JSState service sederhana
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import { Todo } from './todo.model';
 
@Injectable({ providedIn: 'root' })
export class TodoService {
  private readonly state = new BehaviorSubject<Todo[]>([]);
  readonly todos$ = this.state.asObservable();
 
  setTodos(data: Todo[]): void {
    this.state.next(data);
  }
 
  tambah(todo: Todo): void {
    this.state.next([...this.state.getValue(), todo]);
  }
}

BehaviorSubject menyimpan nilai terkini dan mengirimkannya ke subscriber baru. todos$ adalah stream publik yang bisa di-subscribe komponen, sementara state tetap privat. Semua perubahan state lewat method service — itulah satu-satunya jalur.

BehaviorSubject, ReplaySubject, dan State Services

BehaviorSubject vs ReplaySubject

  • BehaviorSubject membutuhkan nilai awal dan mengirim nilai terakhir ke subscriber baru.
  • ReplaySubject menyimpan sejumlah nilai terakhir (tanpa nilai awal wajib) dan mengirimkannya ke subscriber baru.
  • Subject biasa tidak menyimpan nilai; subscriber baru hanya menerima event setelah subscribe.
JSMenggunakan ReplaySubject
import { ReplaySubject } from 'rxjs';
 
const notif$ = new ReplaySubject<string>(3);
 
notif$.next('Perubahan 1');
notif$.next('Perubahan 2');
 
notif$.subscribe((msg) => console.log(msg));

new ReplaySubject<string>(3) menyimpan tiga pesan terakhir. Saat subscribe terjadi setelah dua next, kedua pesan itu langsung diterima subscriber. Pola ini berguna untuk cache kecil atau event yang boleh terlewat.

Subscribe dengan Async Pipe

Komponen menerima state lewat todos$ dan merender dengan pipe async, yang otomatis mengelola subscription:

HTMLRender stream dengan async pipe
<li *ngFor="let todo of todos$ | async; trackBy: trackById">
  {{ todo.judul }}
</li>

todos$ | async men-subscribe stream dan membersihkannya saat komponen dihancurkan — tanpa ngOnDestroy manual dan tanpa risiko memory leak.

Pengenalan NgRx dan Akita

NgRx: Redux untuk Angular

NgRx membawa pola Redux ke Angular: state tunggal, aksi untuk setiap perubahan, dan reducer murni yang menghitung state baru.

JSAksi dan reducer NgRx
import { createAction, createReducer, on } from '@ngrx/store';
 
export const tambahTodo = createAction('[Todo] Tambah', (judul: string) => ({ judul }));
 
const initialState: string[] = [];
 
export const todoReducer = createReducer(
  initialState,
  on(tambahTodo, (state, { judul }) => [...state, judul]),
);

createAction mendefinisikan aksi, createReducer membentuk reducer. Keuntungan NgRx: state dapat di-debug dengan DevTools, satu sumber kebenaran global, dan pola yang konsisten untuk tim besar. Harganya: banyak boilerplate — pertimbangkan hanya untuk state yang benar-benar global dan kompleks.

Akita dan Alternatif

Akita adalah state management yang lebih ringan dengan pendekatan stores dan query, dan memakai API yang lebih mirip OOP. Untuk sebagian besar aplikasi, kombinasi service dengan BehaviorSubject (atau signal) sudah cukup; library eksternal baru layak ditambahkan ketika kompleksitas benar-benar menuntut.

Mengelola Application State dan Side Effects

Side Effects di Satu Tempat

Side effects — request HTTP, penyimpanan localStorage, logging — sebaiknya tidak berserakan di komponen. Pola yang rapi: service state hanya bertanggung jawab atas state, service data menangani HTTP, dan komponen hanya menyatukan keduanya.

JSMemisahkan efek dari state
export class TodoService {
  private readonly state = new BehaviorSubject<Todo[]>([]);
  readonly todos$ = this.state.asObservable();
 
  muat(): void {
    this.http.get<Todo[]>(url).subscribe({
      next: (data) => this.state.next(data),
      error: (err) => console.error('Gagal memuat todo', err),
    });
  }
}

Method muat memicu HTTP, lalu hasilnya masuk ke state melalui state.next. Komponen cukup memanggil muat() dan membaca todos$. Side effects terkumpul di service sehingga komponen tetap ramping dan mudah diuji.

Penutup

Inti yang harus dibawa pulang:

  • Aliran state satu arah: aksi dari komponen, state diperbarui service, stream mengalir kembali.
  • BehaviorSubject menyimpan nilai terkini; ReplaySubject menyimpan sejumlah nilai terakhir.
  • Pipe async mengelola subscription stream secara otomatis.
  • NgRx membawa pola Redux; Akita menawarkan pendekatan yang lebih ringan.
  • Library state management hanya layak dipakai saat kompleksitas menuntut.
  • Pisahkan side effects HTTP dan I/O dari logika state di service.

Di episode 11 selanjutnya kita akan membahas configuration dan environment — memakai environment files dan build configurations, mengatur Angular CLI configuration dan build targets, mengelola feature flags dan API endpoint, serta menangani secrets dan production settings dengan aman.