Skip to main content

Derived & combined state

derived creates a readonly subscribable by mapping another grain. Use combined first when a value depends on several sources — it joins them into one readonly tuple.

ts
const quantity = grain(2);
const unitPrice = grain(12);
const invoice = combined([quantity, unitPrice]);
const total = derived(invoice, ([quantity, price]) => quantity * price);

total(); // 24

Derived values are readonly and update automatically whenever a source grain changes — there's no manual recomputation to wire up.

Your task

total in main.ts is just a static grain stuck at 0. Replace it with a real derived value: combine quantity and unitPrice, then derive their product.

Reveal solution
main.tsts
import { combined, derived, grain } from '@grainular/grains';
import { html, mount } from '@grainular/nord';

const quantity = grain(2);
const unitPrice = grain(12);

const invoice = combined([quantity, unitPrice]);
const total = derived(invoice, ([quantity, price]) => quantity * price);

const App = () => html`
    <main>
        <h1>Invoice</h1>
        <p>${quantity} × $${unitPrice} = $${total}</p>
    </main>
`;

mount(App, { to: document.querySelector('#app') });

Move on to events to attach behavior directly to an element.

Loading playground…