The Problem
You want to react to state changes and run some code as a side effect.
Every reactive library solves this. But how they solve it changes a lot about your code.
Angular Signals — effect()
effect(() => {
console.log('price changed:', price());
});
✅ Simple to read
⚠️ Re-runs when any signal read inside changes
⚠️ Requires Angular's runtime and compiler
⚠️ Lifecycle managed separately from your data
rs-x — The Sequence Expression
const expr = rsx(
'(trackPrice(price), trackQty(quantity), price * quantity)'
)(model);
(a, b, c)is standard JavaScript.
The comma operator evaluates left to right and returns the last value.
rs-x parses it exactly as a JS engine would — no new syntax, no compiler.
Fine-Grained by Default
rsx('(trackPrice(price), trackQty(quantity), price * quantity)')(model)
// ↑ tracks price ↑ tracks quantity ↑ return value
| Change | Re-runs |
|---|---|
model.price = 150 |
trackPrice only |
model.quantity = 5 |
trackQty only |
| Both change | Both re-run |
Each segment tracks its own dependencies — independently.
Conditional Side Effects
rsx('(count > limit && onOverflow(count), count)')(model)
&& short-circuits — standard JavaScript behaviour.
onOverflow is only called when the guard is truthy.
count is still tracked as the return value regardless.
Lifecycle — Zero Ceremony
const expr = rsx('(notify(status), status)')(model);
// Later...
expr.dispose(); // ← every side effect cleaned up automatically
| Angular Signals | rs-x | |
|---|---|---|
| Register | effect(() => {...}) |
part of the expression string |
| Cleanup |
DestroyRef / manual |
expr.dispose() |
| Scope | Angular component | the expression itself |
| Syntax | Framework API | standard JavaScript |
Cross-Property Tracking
// trackView watches userId
// formatName watches profile.name
// Each is independent
rsx('(trackView(userId), formatName(profile.name))')(model)
Change userId → trackView re-runs, formatName does not
Change profile.name → formatName re-runs, trackView does not
The Philosophy
No new API surface. No compiler. Just JavaScript expressions, tracked reactively.
Side effects are co-located with the data they read.
Their lifecycle is owned by the expression, not your application code.
When the expression is disposed — the side effects go with it.
Learn More
📖 Side effects deep dive → https://rsxjs.com/docs/core-concepts/side-effects
▶️ Live playground → https://rsxjs.com/playground
⭐ rs-x on GitHub → github.com/robert-sanders-software-ontwikkeling/rs-x
Top comments (0)