Signals
signal(), computed(), effect() — same API as Angular 20+
Counter — signal + computed
0 count
0 double
neutral sign
Code example
"code-keyword">import { computed, signal } "code-keyword">from '@astro-dx/core';
"code-keyword">import { getElement } "code-keyword">from '@astro-dx/dom';
"code-keyword">import { onClick } "code-keyword">from '@astro-dx/events';
"code-keyword">const count = "code-function">signal(0);
"code-keyword">const double = "code-function">computed(() => "code-function">count() * 2);
"code-function">getElement('#count-display')."code-function">text(count);
"code-function">getElement('#double-display')."code-function">text(double);
"code-function">onClick('#btn-inc', () => count."code-function">update((v) => v + 1));
"code-function">onClick('#btn-dec', () => count."code-function">update((v) => v - 1)); Dynamic deps — conditional effect + peek()
Change branch between A/B and verify re-tracking. Updating peek-only value must not re-run the effect.
Branch
A
Selected value
0
Effect runs
0
A source
1
B source
100
Peek-only signal value: 0
Conditional dependencies snippet
"code-keyword">import { effect, signal } "code-keyword">from '@astro-dx/core';
"code-keyword">const useA = "code-function">signal("code-type">true);
"code-keyword">const a = "code-function">signal(1);
"code-keyword">const b = "code-function">signal(100);
"code-function">effect(() => {
"code-keyword">if ("code-function">useA()) {
console."code-function">log('branch A', "code-function">a());
} "code-keyword">else {
console."code-function">log('branch B', "code-function">b());
}
});
useA."code-function">set("code-type">false);
b."code-function">set(120);
a."code-function">set(2); peek() best practices
"code-keyword">import { effect, signal } "code-keyword">from '@astro-dx/core';
"code-keyword">const visible = "code-function">signal("code-type">true);
"code-keyword">const total = "code-function">signal(99);
"code-keyword">const title = "code-function">signal('Cart');
"code-function">effect(() => {
"code-keyword">if (!"code-function">visible()) "code-keyword">return;
"code-keyword">const trackedTitle = "code-function">title();
"code-keyword">const currentTotal = total."code-function">peek();
console."code-function">log(`${trackedTitle}: ${currentTotal}`);
}); Playground
Edit the code and hit Run to see it live. The preview uses a shimmed version of the astro-dx API.
"code-keyword">import { computed, signal } "code-keyword">from '@astro-dx/core';
"code-keyword">import { getElement } "code-keyword">from '@astro-dx/dom';
"code-keyword">import { onClick } "code-keyword">from '@astro-dx/events';
"code-keyword">const count = "code-function">signal(0);
"code-keyword">const double = "code-function">computed(() => "code-function">count() * 2);
"code-keyword">const sign = "code-function">computed(() => ("code-function">count() > 0 ? 'positive' : "code-function">count() < 0 ? 'negative' : 'neutral'));
"code-function">getElement('#count-display')."code-function">text(count);
"code-function">getElement('#double-display')."code-function">text(double);
"code-function">getElement('#sign-display')."code-function">text(sign);
"code-function">onClick('#btn-inc', () => count."code-function">update((v) => v + 1));
"code-function">onClick('#btn-dec', () => count."code-function">update((v) => v - 1));
"code-function">onClick('#btn-reset', () => count."code-function">set(0)); "code-keyword">import { atom, computed } "code-keyword">from 'nanostores';
"code-keyword">const $count = "code-function">atom(0);
"code-keyword">const $double = "code-function">computed($count, (c) => c * 2);
"code-keyword">const $sign = "code-function">computed($count, (c) => (c > 0 ? 'positive' : c < 0 ? 'negative' : 'neutral'));
$count."code-function">subscribe((v) => {
"code-keyword">const el = document."code-function">querySelector('#count-display');
"code-keyword">if (el) el.textContent = "code-function">String(v);
});
$double."code-function">subscribe((v) => {
"code-keyword">const el = document."code-function">querySelector('#double-display');
"code-keyword">if (el) el.textContent = "code-function">String(v);
});
$sign."code-function">subscribe((v) => {
"code-keyword">const el = document."code-function">querySelector('#sign-display');
"code-keyword">if (el) el.textContent = v;
});
document."code-function">querySelector('#btn-inc')?."code-function">addEventListener('click', () => $count."code-function">set($count."code-function">get() + 1));
document."code-function">querySelector('#btn-dec')?."code-function">addEventListener('click', () => $count."code-function">set($count."code-function">get() - 1));
document."code-function">querySelector('#btn-reset')?."code-function">addEventListener('click', () => $count."code-function">set(0));