Munsif.
AboutExperienceProjectsAchievementsBlogsContact
HomeAboutExperienceProjectsAchievementsBlogsContact
Munsif.

Frontend Developer crafting scalable web applications with modern technologies and clean code practices.

Quick Links

  • About
  • Experience
  • Projects
  • Achievements

Connect

Ā© 2025 Shaik Munsif. All rights reserved.

Built with Next.js & Tailwind

Back to Blogs
Angular

Angular Signals: The Complete Guide to Reactive State Management

Master Angular Signals with this beginner-friendly guide. Learn signal(), computed(), effect() with simple analogies, decision trees, and real-world examples like shopping carts and theme switchers.

Dec 7, 202515 min read
AngularSignalsReactive ProgrammingState Management

What are Angular Signals?

Think of a Signal as a TV channel that always shows the current program. Anyone who tunes in can see what's playing right now. When the program changes, everyone watching sees the update instantly.

In technical terms, a Signal is a wrapper around a value that notifies Angular when that value changes. Unlike Observables (which are like mail delivery - you get values over time), Signals always have a current value you can read.


The Three Signal Primitives

1. signal() - The Value Holder

Analogy: šŸ“ŗ A TV channel broadcasting a value. Anyone can tune in and see the current show.

// Create a signal with initial value
const count = signal(0);

// Read the value (call it like a function)
console.log(count()); // 0

// Update with set() - replace completely
count.set(5);

// Update with update() - transform current
count.update(current => current + 1);

Real-World Example: Shopping Cart Counter

@Component({
  template: `<span>Cart: {{ cartCount() }} items</span>`
})
export class HeaderComponent {
  cartCount = signal(0);

  addToCart() {
    this.cartCount.update(count => count + 1);
  }
}

2. computed() - The Auto-Calculator

Analogy: 🧮 A spreadsheet cell with a formula. When cells it depends on change, it automatically recalculates.

const quantity = signal(2);
const price = signal(50);

// Auto-updates when quantity OR price changes
const total = computed(() => quantity() * price());

console.log(total()); // 100
quantity.set(3);
console.log(total()); // 150 (auto-updated!)

3. effect() - The Watcher

Analogy: šŸ”” A doorbell notification. Whenever something changes, it triggers an action.

const theme = signal('light');

// Runs whenever theme changes
effect(() => {
  document.body.className = theme();
  localStorage.setItem('theme', theme());
});

theme.set('dark'); // Auto-saves!

Decision Tree: Which Primitive Should I Use?


Decision Tree: Signal vs Observable?


set() vs update(): When to Use Which?


Real-World Pattern: E-Commerce Cart

@Injectable({ providedIn: 'root' })
export class CartService {
  // State
  private items = signal<CartItem[]>([]);

  // Computed values (auto-update)
  readonly itemCount = computed(() => 
    this.items().length
  );
  readonly subtotal = computed(() =>
    this.items().reduce((sum, i) => 
      sum + i.price * i.qty, 0)
  );
  readonly total = computed(() => 
    this.subtotal() * 1.08 // with tax
  );

  // Actions
  addItem(product: Product) {
    this.items.update(items => 
      [...items, { ...product, qty: 1 }]
    );
  }
}

Common Mistakes to Avoid

āŒ Don't forget parentheses in templates

<!-- Wrong --> <p>{{ count }}</p>
<!-- Right --> <p>{{ count() }}</p>

āŒ Don't use effect() for derived state

// Wrong - use computed instead!
effect(() => {
  this.fullName = this.firstName() + ' ' + this.lastName();
});

// Right
fullName = computed(() => 
  this.firstName() + ' ' + this.lastName()
);

Summary Cheat Sheet

PrimitivePurposeAnalogyUse Case
signal()Store mutable valuešŸ“ŗ TV ChannelCart count
computed()Derive from signals🧮 SpreadsheetTotal price
effect()Side effectsšŸ”” DoorbellAuto-save

Quick Decision:

  • Store something? → signal()
  • Calculate something? → computed()
  • DO something on change? → effect()

Written by

Shaik Munsif

Read more articles