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

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