computed()
The computed() function creates a derived value that updates automatically when its dependencies change. Computeds are lazy — they only recalculate when read.
Syntax
Section titled “Syntax”const derived = computed(fn)Parameters
Section titled “Parameters”fn
: A function that computes the derived value. Any signals read inside this function become dependencies.
Return value
Section titled “Return value”A Readable<T> — a read-only reactive value:
derived()— Returns the current computed value, tracking this read as a dependencyderived.peek()— Returns the current value without tracking
Description
Section titled “Description”Computeds derive values from other reactive state. When you read signals inside a computed, those reads are tracked. When any dependency changes, the computed will recalculate on the next read.
const firstName = signal('Ada');const lastName = signal('Lovelace');
const fullName = computed(() => `${firstName()} ${lastName()}`);
fullName(); // "Ada Lovelace"
firstName('Grace');fullName(); // "Grace Lovelace"Lazy evaluation
Section titled “Lazy evaluation”Computeds don’t recalculate immediately when dependencies change. They wait until someone reads them:
const count = signal(0);const doubled = computed(() => { console.log('calculating...'); return count() * 2;});
count(1); // Nothing logged yetcount(2); // Still nothingdoubled(); // logs "calculating...", returns 4doubled(); // No log — cached
// Cached until a dependency changesconst items = signal([1, 2, 3, 4, 5]);const sum = computed(() => items().reduce((a, b) => a + b, 0));
sum(); // Calculates: 15sum(); // Cached: 15sum(); // Cached: 15
items([1, 2, 3]);sum(); // Recalculates: 6Composing computeds
Section titled “Composing computeds”Computeds can depend on other computeds:
const items = signal([1, 2, 3]);const count = computed(() => items().length);const sum = computed(() => items().reduce((a, b) => a + b, 0));const average = computed(() => count() > 0 ? sum() / count() : 0);
average(); // 2items([10, 20]);average(); // 15Examples
Section titled “Examples”Filtered list
Section titled “Filtered list”const todos = signal([ { id: 1, text: 'Learn', done: true }, { id: 2, text: 'Build', done: false },]);
const active = computed(() => todos().filter(t => !t.done));const completed = computed(() => todos().filter(t => t.done));const counts = computed(() => ({ active: active().length, completed: completed().length, total: todos().length,}));Expensive calculations
Section titled “Expensive calculations”const data = signal(largeDataset);
const processed = computed(() => { // Only runs when data changes return data() .filter(expensiveFilter) .map(expensiveTransform) .sort(expensiveSort);});Conditional dependencies
Section titled “Conditional dependencies”const showDetails = signal(false);const user = signal({ name: 'Alice', bio: 'Long bio...' });
const display = computed(() => { if (showDetails()) { // Only depends on user when showDetails is true return `${user().name}: ${user().bio}`; } return user().name;});Anti-patterns
Section titled “Anti-patterns”Don’t mutate state in computeds
Section titled “Don’t mutate state in computeds”Computeds should be pure — no side effects:
// BAD — side effect in computedconst doubled = computed(() => { console.log('computing'); // side effect otherSignal(count() * 2); // mutation! return count() * 2;});
// GOOD — pure computationconst doubled = computed(() => count() * 2);Don’t create circular dependencies
Section titled “Don’t create circular dependencies”// BAD — infinite loopconst a = computed(() => b() + 1);const b = computed(() => a() + 1);Don’t return elements from computeds
Section titled “Don’t return elements from computeds”Computeds return values, not DOM elements. Use match() for conditional rendering:
// BAD — computed can't return elementsconst content = computed(() => show() ? el('div')('Yes') : el('div')('No'));
// GOOD — use match for conditional elementsmatch(show, (s) => s ? el('div')('Yes') : el('div')('No'))