Bird
Raised Fist0
Angularframework~5 mins

Signals as modern state primitive in Angular

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Introduction

Signals help keep track of changing data in your app simply and clearly. They make your app update automatically when data changes.

When you want to store and react to simple data changes like a counter or form input.
When you want your UI to update automatically without writing extra code.
When you want to avoid complex state management and keep code easy to read.
When you want to share reactive data between components easily.
When you want to improve performance by updating only what changes.
Syntax
Angular
import { Component, signal } from '@angular/core';

@Component({
  selector: 'app-counter',
  standalone: true,
  template: `
    <button (click)="increment()">Increment</button>
    <p>Count: {{ count() }}</p>
  `
})
export class CounterComponent {
  count = signal(0);

  increment() {
    this.count.update(current => current + 1);
  }
}

The signal function creates a reactive value that you can read by calling it like a function.

Use update to change the signal's value based on its current value.

Examples
Creating a signal with initial value 0, reading it, then setting it to 5.
Angular
const count = signal(0);
console.log(count()); // 0
count.set(5);
console.log(count()); // 5
Signal holding a string value that changes from 'Alice' to 'Bob'.
Angular
const name = signal('Alice');
name.set('Bob');
console.log(name()); // Bob
Using update to add 5 to the current score.
Angular
const score = signal(10);
score.update(current => current + 5);
console.log(score()); // 15
Signal can hold any type, including null for empty state.
Angular
const emptySignal = signal(null);
console.log(emptySignal()); // null
Sample Program

This component uses a signal to keep track of how many times the button is clicked. Each click updates the signal, and the UI updates automatically.

Angular
import { Component, signal } from '@angular/core';

@Component({
  selector: 'app-click-tracker',
  standalone: true,
  template: `
    <button (click)="trackClick()">Click me</button>
    <p>You clicked {{ clicks() }} times.</p>
  `
})
export class ClickTrackerComponent {
  clicks = signal(0);

  trackClick() {
    this.clicks.update(currentClicks => currentClicks + 1);
  }
}

// When the button is clicked 3 times, the displayed text updates automatically to:
// You clicked 3 times.
OutputSuccess
Important Notes

Signals update synchronously and immediately notify any part of the app that uses them.

Time complexity for reading or updating a signal is O(1).

Common mistake: forgetting to call the signal as a function to read its value (e.g., use count() not count).

Use signals for simple, local state. For complex shared state, consider Angular's other state management tools.

Summary

Signals are simple reactive values that update your UI automatically.

Use signal() to create, call the signal like a function to read (e.g., count()), and set() or update() to change values.

They help keep your code clean and your app responsive.

Practice

(1/5)
1. What is the main purpose of using signal() in Angular?
easy
A. To style elements dynamically
B. To create a reactive state value that updates the UI automatically
C. To handle HTTP requests
D. To define a new component

Solution

  1. Step 1: Understand the role of signal()

    signal() creates a reactive value that Angular tracks for changes.
  2. Step 2: Connect signal() to UI updates

    When the signal value changes, Angular automatically updates the UI where it is used.
  3. Final Answer:

    To create a reactive state value that updates the UI automatically -> Option B
  4. Quick Check:

    signal() creates reactive state [OK]
Hint: Signals hold reactive values that auto-update UI [OK]
Common Mistakes:
  • Confusing signals with components
  • Thinking signals handle HTTP
  • Assuming signals are for styling
2. Which of the following is the correct way to create a signal with initial value 10 in Angular?
easy
A. const count = signal(10);
B. const count = new Signal(10);
C. const count = createSignal(10);
D. const count = signal.set(10);

Solution

  1. Step 1: Recall the syntax for creating signals

    Angular uses signal(initialValue) to create a signal with a starting value.
  2. Step 2: Check each option's syntax

    Only const count = signal(10); matches the correct syntax. Others use incorrect constructors or methods.
  3. Final Answer:

    const count = signal(10); -> Option A
  4. Quick Check:

    signal() creates with initial value [OK]
Hint: Use signal(value) to create signals [OK]
Common Mistakes:
  • Using new keyword with signal
  • Calling non-existent createSignal function
  • Trying to set value during creation
3. Given the code:
const count = signal(0);
count.set(5);
console.log(count());

What will be printed in the console?
medium
A. 5
B. 0
C. undefined
D. Error: count is not a function

Solution

  1. Step 1: Understand signal creation and update

    The signal count starts at 0, then set(5) changes its value to 5.
  2. Step 2: Reading the signal value

    Calling count() returns the current value, which is 5 after the update.
  3. Final Answer:

    5 -> Option A
  4. Quick Check:

    count.set(5) updates value, count() reads it [OK]
Hint: Use count() to read updated signal value [OK]
Common Mistakes:
  • Thinking count() returns initial value
  • Confusing set() with reading value
  • Assuming count is not callable
4. Identify the error in this Angular signal code:
const name = signal('Alice');
name.update(name + ' Smith');
medium
A. Incorrect initial value type for signal
B. Missing parentheses when calling signal()
C. Using update() with a string instead of a function
D. Using set() instead of update()

Solution

  1. Step 1: Understand update() usage

    update() expects a function that receives the current value and returns the new value.
  2. Step 2: Analyze the code's argument to update()

    The code passes name + ' Smith' which is a string, not a function, causing an error.
  3. Final Answer:

    Using update() with a string instead of a function -> Option C
  4. Quick Check:

    update() needs a function argument [OK]
Hint: Pass a function to update(), not a direct value [OK]
Common Mistakes:
  • Passing value directly to update()
  • Confusing set() and update() usage
  • Ignoring function argument requirement
5. You want to create a signal that holds a list of numbers and add a new number to it reactively. Which code correctly updates the signal to add number 7?
hard
A. numbers.push(7);
B. numbers.set(numbers() + 7);
C. numbers = signal([...numbers(), 7]);
D. numbers.update(list => [...list, 7]);

Solution

  1. Step 1: Understand how to update array signals

    Signals hold values immutably; to add an item, create a new array with the old items plus the new one.
  2. Step 2: Check each option's correctness

    numbers.update(list => [...list, 7]); uses update() with a function that returns a new array including 7, which is correct.
    numbers.set(numbers() + 7); tries to add 7 to an array directly, causing a type error.
    numbers = signal([...numbers(), 7]); tries to reassign the signal variable, which is incorrect.
    numbers.push(7); calls push() on the signal itself, which is not valid.
  3. Final Answer:

    numbers.update(list => [...list, 7]); -> Option D
  4. Quick Check:

    Use update() with function returning new array [OK]
Hint: Use update(fn) to immutably add items to array signals [OK]
Common Mistakes:
  • Trying to mutate signal value directly
  • Reassigning signal variable instead of updating
  • Using set() with wrong value type