The mental model#
Instead of describing the entire component again whenever state changes, Zidom records which reactive binding reads which signal. On a signal write, that binding receives a scheduled update. A component is primarily a setup function that creates nodes and their reactive relationships.
Component setup | v JSX runtime ------> Real DOM nodes | v Signal subscriptions | count.value changes | v Dependent text/attribute updatesSignals are the smallest unit#
import { signal, computed } from '@zidomjs/core';const count = signal(0);const double = computed(() => count.value * 2);const view = <section> <output>{count}</output> <output>{double}</output></section>;count.value = 1;The runtime can update both bound text nodes without calling the component that created the view again. The browser still performs any necessary style, layout and paint work.
Structural updates are different#
Conditionally changing which element exists is a structural update. JSX getters can replace scoped regions, and For uses stable keys to retain row identity during list reordering.
- A scalar text binding can reuse its text node.
- A conditional branch can dispose its old subtree and construct a new one.
- A keyed list can reorder existing rows without remounting the same keyed item.
Ownership matters#
Mounting establishes a lifetime. When a view unmounts, its subscriptions, refs and event listeners are disposed. Long-lived signals and effects created outside a scope require explicit cleanup by the application.
Optional build-time compilation#
An experimental TSX compiler can find certain local signals and turn .value expressions into reactive getters. It can also opt in to conservative static and dynamic templates. Explicit signals and getters work without the compiler.
Learn the implementation in Signals & computed, Reactive rendering and Effects & lifecycle.
Run the example#
See the Zidom counter example and inspect the exact source next to the result.