v0.5.1 — Reactive components & dependency-aware OOB swaps
The release that introduced reactivity — dependency-aware out-of-band HTMX swaps driven by a declarative state→view graph you declare on your components. A mutation route re-emits exactly the mounted regions that depend on what changed, with no per-endpoint wiring.
✨ Reactive components (#13–#21)
ReactiveComponent+ a declared dependency graph — a component lists the state keys itreacts_to;oob_swapsre-emits the mounted regions whose keys intersect a route's dirtied set (#13, #17).- Auto-loaded dependents —
render(dirtied=, mounted=)reloads and re-emits dependent regions ashx-swap-oobfragments (#15). - Hash-gating — a region is re-emitted only when its freshly computed
state_hash()differs from the hash the client reported; unchanged regions are skipped (#14). - Process-global
load()cache with dependency-keyed invalidation — dependents reload once per request and evict precisely on mutation (#16). - Instance-keyed dependencies — many mounted instances of one type (rows, cards) with a keyed
render()auto-load entry point (#21). - Ergonomics —
reacts_to(renamed fromdepends_on) (#19); componentiddefaults to the kebab-cased class name (#20); bare instance-tier stems ({\"todo\"}); enums accepted asload()keys; type hints across the reactive/cache modules. - A runnable
examples/reactive_tododemo + integration tests (#18).
🐛 Fixes
- Keyed primary served fresh, not from a stale cache (#22) —
Cls.render(key, …)evicts dirtied keys before loading the primary, so the route response reflects the just-applied mutation even when the load cache was warmed by the initial page load.
Install
pip install pyjinhx==0.5.1Full reactivity guide: docs/reactivity.md · Full changelog: v0.4.2...v0.5.1