Skip to content
Tools— browse docs
On this page

Step 4: A computed column

Quantity times price is a Total — but it never gets its own field.

Quantity times price is a Total. The instinct is to give it a field and keep it updated on every edit — but then it's just another thing that can drift out of sync with the numbers it came from. Compute it instead:

// Never stored — recomputed from data.rows on every render, so it can't drift.
const total = data.rows.reduce((sum, row) => sum + row.quantity * row.price, 0)

Add a Total column per row, and a sum in the footer.

A number nobody types in
src/codec.ts + src/tool.tsx Lines 44 to 45, 60, 90 to 92 and 104 highlighted.

Edit and the example re-runs. Tab indents; press Escape to leave the editor.

Running · your edits, live
Starting the example…

You should see: change a quantity, and its row's Total updates immediately — and so does the sum in the footer. Nothing wired them together directly; both just read the same data.rows.

Note:

If you ever find yourself writing actions.set("total", …) next to every cell edit, that's the tell. A value that's always derivable from other fields doesn't belong in the codec — compute it in render instead, and it can never be wrong.

Next steps