Computed
Computed values are derived from signals. They update automatically when their dependencies change. Think of them as formulas that always stay in sync.
Basic Usage
const { signal, computed } = Lightview;
const count = signal(10);
const doubled = computed(() => count.value * 2);
console.log(doubled.value); // 20
count.value = 5;
console.log(doubled.value); // 10 (automatically updated!)
Chaining Computed Values
Computed values can depend on other computed values:
const price = signal(100);
const quantity = signal(2);
const taxRate = signal(0.1);
const subtotal = computed(() => price.value * quantity.value);
const tax = computed(() => subtotal.value * taxRate.value);
const total = computed(() => subtotal.value + tax.value);
console.log(total.value); // 220
Reading Computed Values
// Same as signals - two ways to read
console.log(doubled.value); // Property access
console.log(doubled()); // Function call
In the UI
Computed values work seamlessly in your UI, just like signals:
const price = signal(100);
const quantity = signal(1);
const total = computed(() => price.value * quantity.value);
div(
p(() => `Price: $${price.value}`),
p(() => `Quantity: ${quantity.value}`),
p(() => `Total: $${total.value}`),
button({ onclick: () => quantity.value++ }, 'Add One')
)
When to Use Computed
- Derived values — Calculations based on other state
- Formatting — Display formatting (dates, currency, etc.)
- Filtering/Sorting — Processed lists from raw data
- Validation — Form validity based on field values
Example: Filtered List
const todos = signal([
{ text: 'Learn Lightview', done: true },
{ text: 'Build something cool', done: false },
{ text: 'Ship it', done: false }
]);
const filter = signal('all'); // 'all', 'active', 'done'
const filteredTodos = computed(() => {
const list = todos.value;
switch (filter.value) {
case 'active': return list.filter(t => !t.done);
case 'done': return list.filter(t => t.done);
default: return list;
}
});
Example: Form Validation
const email = signal('');
const password = signal('');
const isEmailValid = computed(() =>
/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email.value)
);
const isPasswordValid = computed(() =>
password.value.length >= 8
);
const canSubmit = computed(() =>
isEmailValid.value && isPasswordValid.value
);
button({ disabled: () => !canSubmit.value }, 'Submit')
Computed vs Effect
Both react to changes, but serve different purposes:
| Computed | Effect |
|---|---|
| Returns a value | Doesn't return anything useful |
| Pure (no side effects) | For side effects |
| Lazy (computed when read) | Eager (runs immediately) |
| Use in UI for derived data | Use for logging, storage, API calls |