Bird
Raised Fist0
Angularframework~15 mins

Computed signals for derived values in Angular - Deep Dive

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
Overview - Computed signals for derived values
What is it?
Computed signals are special reactive values in Angular that automatically update when their input signals change. They let you create values derived from other signals without manually managing updates. This helps keep your UI and logic in sync effortlessly. Think of them as formulas that recalculate whenever their ingredients change.
Why it matters
Without computed signals, developers must manually track and update derived values, which can lead to bugs and complicated code. Computed signals simplify this by automatically recalculating derived data, making apps more reliable and easier to maintain. This reactive approach improves user experience by ensuring the UI always shows the latest data without extra work.
Where it fits
Before learning computed signals, you should understand basic Angular signals and reactive programming concepts. After mastering computed signals, you can explore more advanced state management patterns and Angular's standalone reactive APIs for building scalable applications.
Mental Model
Core Idea
A computed signal is a reactive formula that automatically recalculates its value whenever its input signals change.
Think of it like...
It's like a recipe that automatically updates the taste of a dish whenever you change any ingredient, without you having to cook it again manually.
Signals (inputs) ──▶ Computed Signal (formula) ──▶ Derived Value (output)
  │                     ▲
  └─────────────────────┘

When any input signal changes, the computed signal recalculates and updates the derived value.
Build-Up - 7 Steps
1
FoundationUnderstanding Angular Signals Basics
🤔
Concept: Signals hold reactive values that notify dependents when they change.
In Angular, a signal is a special object that stores a value and lets other parts of your app react when this value changes. You create a signal with `signal(initialValue)`. When you update the signal, anything that uses it automatically updates too.
Result
You get a reactive value container that triggers updates in your app when changed.
Understanding signals is key because computed signals build on this reactive value concept to derive new values automatically.
2
FoundationCreating Simple Signals and Reading Values
🤔
Concept: You can create signals and read their current value using `.()`.
Example: const count = signal(0); console.log(count()); // prints 0 count.set(5); console.log(count()); // prints 5 Signals hold values and expose them via calling the signal as a function.
Result
You can store and retrieve reactive values easily.
Knowing how to create and read signals is the foundation for building reactive logic and computed signals.
3
IntermediateIntroducing Computed Signals for Derived Values
🤔Before reading on: do you think computed signals update automatically or require manual triggers? Commit to your answer.
Concept: Computed signals automatically recalculate their value based on other signals they depend on.
You create a computed signal with `computed(() => expression)`. The expression uses other signals. When any of those signals change, the computed signal recalculates. Example: const count = signal(1); const double = computed(() => count() * 2); console.log(double()); // 2 count.set(3); console.log(double()); // 6 (auto updated)
Result
Derived values stay in sync automatically without manual updates.
Understanding automatic recalculation prevents bugs from stale data and simplifies reactive code.
4
IntermediateUsing Computed Signals in Angular Components
🤔Before reading on: do you think computed signals can be used directly in templates or only in component code? Commit to your answer.
Concept: Computed signals can be used inside Angular components and templates to reflect derived reactive data.
Inside a component: @Component({ selector: 'app-counter', template: `

Double: {{ double() }}

` }) export class CounterComponent { count = signal(1); double = computed(() => this.count() * 2); } The template automatically updates when `count` changes because `double` is reactive.
Result
UI updates automatically to show derived values without extra code.
Knowing computed signals integrate seamlessly with templates helps build clean reactive UIs.
5
IntermediateAvoiding Unnecessary Recomputations
🤔Before reading on: do you think computed signals always recompute on every change or only when their dependencies change? Commit to your answer.
Concept: Computed signals only recompute when their dependent signals change, optimizing performance.
Computed signals track which signals they read during computation. If none of those signals change, the computed signal returns cached value. Example: const a = signal(1); const b = signal(2); const sum = computed(() => a() + b()); If only `a` changes, `sum` recomputes. If unrelated signals change, `sum` does not.
Result
Efficient updates prevent wasted work and improve app speed.
Understanding dependency tracking helps write performant reactive code.
6
AdvancedHandling Side Effects with Computed Signals
🤔Before reading on: do you think computed signals should contain side effects like logging or HTTP calls? Commit to your answer.
Concept: Computed signals should be pure and side-effect free; side effects belong in effects or other reactive constructs.
Computed signals are meant to derive values only. Putting side effects inside them can cause unpredictable behavior. Instead, use `effect(() => { ... })` for side effects triggered by signals. Example: const count = signal(0); const double = computed(() => count() * 2); effect(() => console.log('Double is', double()));
Result
Clear separation of pure computation and side effects leads to predictable apps.
Knowing this prevents subtle bugs and keeps reactive logic clean and maintainable.
7
ExpertComputed Signals Internals and Change Detection
🤔Before reading on: do you think Angular's computed signals use dirty checking or dependency tracking under the hood? Commit to your answer.
Concept: Computed signals use fine-grained dependency tracking to know exactly when to recompute, avoiding full dirty checks.
When a computed signal runs, Angular records which signals it reads. These become dependencies. When any dependency changes, Angular marks the computed signal as stale. On next read, it recomputes the value. This lazy recomputation avoids unnecessary work. This mechanism integrates with Angular's change detection to update the UI efficiently.
Result
Highly efficient reactive updates with minimal overhead.
Understanding this mechanism explains why computed signals are both fast and reliable in large apps.
Under the Hood
Computed signals work by running their computation function and tracking all signals accessed during that run. These accessed signals become dependencies. When any dependency signal changes, the computed signal is marked as needing recomputation. The next time the computed signal's value is requested, it recalculates by running the function again. This lazy evaluation ensures computations happen only when needed. Angular integrates this with its change detection to update the UI efficiently.
Why designed this way?
This design avoids expensive full checks of all reactive values by tracking exact dependencies. It balances performance and correctness, preventing unnecessary recomputations. Earlier reactive systems used polling or manual subscriptions, which were error-prone or inefficient. Angular's computed signals provide a declarative, automatic, and optimized way to keep derived values up to date.
┌───────────────┐       ┌───────────────┐
│ Input Signal 1│──────▶│               │
│ (e.g. count)  │       │ Computed      │
└───────────────┘       │ Signal        │─────▶ Derived Value
                        │ (formula)     │
┌───────────────┐       │               │
│ Input Signal 2│──────▶│               │
│ (e.g. factor) │       └───────────────┘
└───────────────┘

When Input Signal 1 or 2 changes, Computed Signal marks itself stale.
On next read, it recomputes and updates Derived Value.
Myth Busters - 4 Common Misconceptions
Quick: Do computed signals run their function every time you read them, or only when dependencies change? Commit to your answer.
Common Belief:Computed signals run their function every time you read them, so they are expensive.
Tap to reveal reality
Reality:Computed signals cache their value and only recompute when their dependencies change, making them efficient.
Why it matters:Believing they always recompute can scare developers away from using them, missing out on performance benefits.
Quick: Can you put side effects like HTTP calls inside computed signals safely? Commit to yes or no.
Common Belief:It's fine to put side effects inside computed signals since they run automatically.
Tap to reveal reality
Reality:Computed signals should be pure and side-effect free; side effects belong in effects or other reactive constructs.
Why it matters:Putting side effects inside computed signals can cause unpredictable behavior and bugs.
Quick: Do computed signals update their value immediately when dependencies change, or only when read next? Commit to your answer.
Common Belief:Computed signals update their value immediately as soon as any dependency changes.
Tap to reveal reality
Reality:Computed signals mark themselves stale on dependency change but recompute lazily on next read.
Why it matters:Understanding lazy recomputation helps avoid confusion about when values update and improves debugging.
Quick: Are computed signals a replacement for all state management in Angular? Commit to yes or no.
Common Belief:Computed signals replace the need for any other state management tools.
Tap to reveal reality
Reality:Computed signals are a tool for derived reactive values but do not replace full state management solutions like NgRx or services.
Why it matters:Overreliance on computed signals alone can lead to poor app architecture and scalability issues.
Expert Zone
1
Computed signals track dependencies dynamically during each run, so conditional logic inside the computation can change which signals are tracked.
2
Computed signals use lazy evaluation, meaning they only recompute when their value is requested, not immediately on dependency change.
3
Stacking computed signals (computed depending on other computed) creates a dependency graph that Angular efficiently manages to minimize recomputations.
When NOT to use
Avoid using computed signals for side effects or asynchronous operations; use Angular effects or observables instead. Also, for complex global state management, consider NgRx or other dedicated libraries rather than relying solely on signals.
Production Patterns
In real apps, computed signals are used to derive UI state like filtered lists, formatted dates, or combined flags. They are combined with effects for side effects and signals for base state. Developers often create reusable computed signals for common derived logic to keep components clean.
Connections
Functional Programming
Computed signals embody the concept of pure functions and immutability by deriving values from inputs without side effects.
Understanding pure functions helps grasp why computed signals must be side-effect free and deterministic.
Spreadsheets
Computed signals work like spreadsheet formulas that automatically update when input cells change.
Knowing how spreadsheets recalculate cells clarifies how computed signals track dependencies and update lazily.
Observer Pattern (Software Design)
Computed signals implement a refined observer pattern where dependents subscribe to changes in dependencies.
Recognizing this pattern explains how Angular efficiently propagates changes through reactive values.
Common Pitfalls
#1Putting side effects like logging or HTTP calls inside computed signals.
Wrong approach:const data = computed(() => { fetch('/api').then(...); return someSignal(); });
Correct approach:const data = signal(null); effect(() => { fetch('/api').then(response => data.set(response)); });
Root cause:Misunderstanding that computed signals should be pure and side-effect free.
#2Manually updating derived values instead of using computed signals.
Wrong approach:let doubleValue = 0; count.set(5); doubleValue = count() * 2; // manual update needed everywhere
Correct approach:const doubleValue = computed(() => count() * 2);
Root cause:Not leveraging reactive derivation leads to error-prone and verbose code.
#3Expecting computed signals to recompute immediately on dependency change.
Wrong approach:console.log(double()); count.set(3); // expecting double() to have updated immediately without reading it again
Correct approach:count.set(3); console.log(double()); // recomputes now on read
Root cause:Confusing lazy recomputation with immediate update semantics.
Key Takeaways
Computed signals in Angular automatically derive values from other signals, keeping data in sync without manual updates.
They track dependencies dynamically and recompute lazily, making reactive updates efficient and predictable.
Computed signals must be pure and free of side effects; side effects belong in effects or other reactive constructs.
Using computed signals simplifies UI updates and reduces bugs caused by stale or manually managed derived data.
Understanding computed signals connects to broader concepts like pure functions, observer patterns, and spreadsheet formulas.

Practice

(1/5)
1. What is the main purpose of a computed signal in Angular's signal system?
easy
A. To replace all signals with a single global state
B. To store static data that never changes
C. To automatically update a value based on other signals when they change
D. To manually trigger UI updates

Solution

  1. Step 1: Understand what computed signals do

    Computed signals derive their value from other signals and update automatically when those signals change.
  2. Step 2: Compare options with this behavior

    Only To automatically update a value based on other signals when they change describes automatic updates based on dependencies, which matches computed signals.
  3. Final Answer:

    To automatically update a value based on other signals when they change -> Option C
  4. Quick Check:

    Computed signals = auto-update derived values [OK]
Hint: Computed signals auto-update when dependencies change [OK]
Common Mistakes:
  • Thinking computed signals store static data
  • Confusing manual updates with automatic updates
  • Assuming computed signals replace all signals
2. Which of the following is the correct syntax to create a computed signal in Angular?
easy
A. const total = computed(() => price() + tax());
B. const total = signal(() => price + tax);
C. const total = computed(price + tax);
D. const total = signal(price() + tax());

Solution

  1. Step 1: Recall computed signal syntax

    Computed signals use computed(() => ...) with a function returning the derived value.
  2. Step 2: Check each option

    const total = computed(() => price() + tax()); correctly uses computed(() => price() + tax()). const total = signal(() => price + tax); wrongly uses signal and no function. const total = computed(price + tax); misses the function wrapper. const total = signal(price() + tax()); uses signal instead of computed.
  3. Final Answer:

    const total = computed(() => price() + tax()); -> Option A
  4. Quick Check:

    Computed syntax = computed(() => value) [OK]
Hint: Use computed(() => ...) with a function for derived values [OK]
Common Mistakes:
  • Using signal() instead of computed() for derived values
  • Passing expressions directly without a function
  • Not calling dependent signals as functions
3. Given the code below, what will be logged after count.set(5) is called?
const count = signal(0);
const double = computed(() => count() * 2);

console.log(double());
count.set(5);
console.log(double());
medium
A. 0 then 10
B. 0 then 0
C. NaN then 10
D. Error at runtime

Solution

  1. Step 1: Evaluate initial values

    Initially, count is 0, so double() returns 0 * 2 = 0.
  2. Step 2: After count.set(5)

    Setting count to 5 updates double automatically. Calling double() now returns 5 * 2 = 10.
  3. Final Answer:

    0 then 10 -> Option A
  4. Quick Check:

    Initial double=0, after update=10 [OK]
Hint: Computed updates automatically after signal changes [OK]
Common Mistakes:
  • Assuming computed does not update after set()
  • Forgetting to call signals as functions
  • Expecting errors due to missing subscriptions
4. Identify the error in the following code snippet using computed signals:
const price = signal(100);
const tax = signal(0.1);
const total = computed(() => price + tax * price);

console.log(total());
medium
A. Computed signals cannot use arithmetic operations
B. Signals must be called as functions inside computed
C. Signals cannot be used inside computed
D. Missing initial value for tax signal

Solution

  1. Step 1: Check how signals are accessed

    Signals are functions and must be called with () to get their current value.
  2. Step 2: Analyze the computed expression

    The expression uses price and tax directly without calling them, so it uses the signal objects, not their values.
  3. Final Answer:

    Signals must be called as functions inside computed -> Option B
  4. Quick Check:

    Access signals with () inside computed [OK]
Hint: Always call signals as functions inside computed [OK]
Common Mistakes:
  • Using signal variables directly without ()
  • Thinking computed disallows arithmetic
  • Ignoring signal initial values
5. You want to create a computed signal that returns the full name by combining two signals: firstName and lastName. Which code correctly updates the full name when either signal changes and avoids unnecessary recomputations?
hard
A. const fullName = computed(() => firstName() + lastName());
B. const fullName = signal(`${firstName()} ${lastName()}`);
C. const fullName = computed(() => firstName + ' ' + lastName);
D. const fullName = computed(() => `${firstName()} ${lastName()}`);

Solution

  1. Step 1: Understand the goal

    The computed signal should combine firstName and lastName signals and update automatically when either changes.
  2. Step 2: Evaluate each option

    const fullName = computed(() => `${firstName()} ${lastName()}`); correctly calls both signals as functions and concatenates with a space. const fullName = signal(`${firstName()} ${lastName()}`); uses signal which won't update automatically. const fullName = computed(() => firstName + ' ' + lastName); uses signal variables directly without calling them. const fullName = computed(() => firstName() + lastName()); concatenates without space.
  3. Final Answer:

    const fullName = computed(() => `${firstName()} ${lastName()}`); -> Option D
  4. Quick Check:

    Call signals with () and combine with space [OK]
Hint: Use computed with template literals calling signals () [OK]
Common Mistakes:
  • Using signal() instead of computed() for derived values
  • Not calling signals as functions
  • Forgetting space between names