DEV Community

Renuka Patil
Renuka Patil

Posted on

`Subject` vs `BehaviorSubject` in **RxJS

Here’s a detailed comparison and explanation of Subject vs BehaviorSubject in RxJS (Reactive Extensions for JavaScript)—widely used in Angular for state management, communication between components, and reactive programming.


Subject vs BehaviorSubject in RxJS

Feature Subject BehaviorSubject
Initial Value ❌ Does not hold a default value ✅ Requires an initial value
Replay Last Value ❌ New subscribers do not get previous emissions ✅ New subscribers immediately receive the last emitted value
Common Use Case Events (e.g., button clicks, form submissions) State or data (e.g., current user, theme, language settings)
Value Access ❌ Cannot access the current value directly ✅ Can get current value via .value property
Multicasting ✅ Yes ✅ Yes

🔹 What is a Subject?

A Subject is a special type of Observable that allows multicasting to multiple observers.

🔧 Example:

const subject = new Subject<number>();

subject.subscribe(val => console.log('Subscriber 1:', val));
subject.next(1); // Output: Subscriber 1: 1

subject.subscribe(val => console.log('Subscriber 2:', val));
subject.next(2);
// Output:
// Subscriber 1: 2
// Subscriber 2: 2
Enter fullscreen mode Exit fullscreen mode

Note: Subscriber 2 didn't receive 1 because it subscribed after it was emitted.


🔹 What is a BehaviorSubject?

A BehaviorSubject stores the latest value and emits it immediately to new subscribers.

🔧 Example:

const behaviorSubject = new BehaviorSubject<number>(0); // Initial value

behaviorSubject.subscribe(val => console.log('Subscriber 1:', val)); 
// Output: Subscriber 1: 0 (gets initial value)

behaviorSubject.next(1);

behaviorSubject.subscribe(val => console.log('Subscriber 2:', val));
// Output: Subscriber 2: 1 (gets last emitted value)

behaviorSubject.next(2);
// Output:
// Subscriber 1: 2
// Subscriber 2: 2
Enter fullscreen mode Exit fullscreen mode

🔍 Accessing Current Value (BehaviorSubject only):

const value = behaviorSubject.value;
console.log('Current Value:', value);
Enter fullscreen mode Exit fullscreen mode

🧠 When to Use Which?

Use Case Use
You want to broadcast events (no stored value) Subject
You need to remember the last value or have a default BehaviorSubject
You want new subscribers to immediately get the latest data BehaviorSubject

✅ Summary

  • Use Subject for one-off events.
  • Use BehaviorSubject for holding current state and updating all listeners.

Sure! Let's go through real-world, project-based examples of how Subject and BehaviorSubject are used in Angular applications, especially for communication between components and state management.


📦 Project Scenario: Angular E-commerce App

🎯 Use Case 1: Cart State Management (Using BehaviorSubject)

You want to maintain a global cart state and reflect updates across components like the header, cart page, and product list.

✅ Service (cart.service.ts)

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

@Injectable({ providedIn: 'root' })
export class CartService {
  private cartItems = new BehaviorSubject<any[]>([]);
  cartItems$ = this.cartItems.asObservable();

  addToCart(product: any) {
    const currentItems = this.cartItems.value;
    this.cartItems.next([...currentItems, product]);
  }

  removeFromCart(productId: string) {
    const updatedItems = this.cartItems.value.filter(p => p.id !== productId);
    this.cartItems.next(updatedItems);
  }

  getCartItems() {
    return this.cartItems.value;
  }
}
Enter fullscreen mode Exit fullscreen mode

🧩 Header Component (header.component.ts) – Show cart count

this.cartService.cartItems$.subscribe(items => {
  this.cartCount = items.length;
});
Enter fullscreen mode Exit fullscreen mode

📦 Cart Page (cart.component.ts) – Show cart details

this.cartService.cartItems$.subscribe(items => {
  this.cartItems = items;
});
Enter fullscreen mode Exit fullscreen mode

💡 Why BehaviorSubject?

  • Holds the latest cart state.
  • Any new subscriber (component) instantly gets current cart items.
  • Easily allows centralized state management.

🎯 Use Case 2: Notification System (Using Subject)

You want to show toast notifications (success, error, etc.) triggered by different parts of the app.

✅ Notification Service (notification.service.ts)

import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';

@Injectable({ providedIn: 'root' })
export class NotificationService {
  private notificationSubject = new Subject<string>();
  notification$ = this.notificationSubject.asObservable();

  show(message: string) {
    this.notificationSubject.next(message);
  }
}
Enter fullscreen mode Exit fullscreen mode

🧩 Notification Component (notification.component.ts)

this.notificationService.notification$.subscribe(msg => {
  this.message = msg;
  // Display the toast
});
Enter fullscreen mode Exit fullscreen mode

🧩 Trigger Notification From Anywhere

this.notificationService.show('Product added to cart!');
Enter fullscreen mode Exit fullscreen mode

💡 Why Subject?

  • Only emits when a new event occurs.
  • No need to store previous values.
  • Ideal for short-lived, one-time event streams.

🎯 Use Case 3: Login State Management (Using BehaviorSubject)

Track user login status and show/hide UI elements conditionally.

✅ Auth Service (auth.service.ts)

private isLoggedInSubject = new BehaviorSubject<boolean>(false);
isLoggedIn$ = this.isLoggedInSubject.asObservable();

login(userCredentials) {
  // after successful login
  this.isLoggedInSubject.next(true);
}

logout() {
  this.isLoggedInSubject.next(false);
}
Enter fullscreen mode Exit fullscreen mode

🧩 Sidebar Component

this.authService.isLoggedIn$.subscribe(loggedIn => {
  this.showMenu = loggedIn;
});
Enter fullscreen mode Exit fullscreen mode

✅ Summary

Feature Subject BehaviorSubject
When to Use Emit events without state (e.g., notifications) Share application state (e.g., cart, login info)
Project Example Toast notifications, chat messages Cart management, login state, theme switching

Happy Coding!

Top comments (0)