Skip to content

Instantly share code, notes, and snippets.

@rodydavis
Last active March 1, 2025 19:23
import 'package:jaspr/jaspr.dart';
import 'package:signals/signals_core.dart';
import 'watch.dart';
import 'embedded_counter.dart';
class Counter extends StatefulComponent {
const Counter({super.key});
@override
State<Counter> createState() => CounterState();
}
class CounterState extends State<Counter> {
final count = signal(0);
@override
Iterable<Component> build(BuildContext context) sync* {
yield div(classes: 'counter', [
button(
onClick: () {
count.value--;
},
[text('-')],
),
span([text('${count.watch(context)}')]),
button(
onClick: () {
count.value++;
},
[text('+')],
),
]);
yield EmbeddedCounter(
count: count.value,
onChange: (value) {
count.value = value;
},
);
}
}
import 'package:jaspr/browser.dart';
import 'package:signals/signals_core.dart';
class SignalsContext {
final BuildContext context;
late Element element = context as Element;
SignalsContext(this.context) {
assert(
context is Element, 'SignalsContext must be created with an Element');
}
final _cleanup = <VoidCallback>[];
final _signals = <ReadonlySignal>{};
bool has(ReadonlySignal signal) {
return _signals.contains(signal);
}
void add(ReadonlySignal signal) {
if (_signals.add(signal)) {
_cleanup.add(signal.subscribe((val) {
if (!element.dirty) element.markNeedsBuild();
}));
}
}
void dispose() {
for (var cleanup in _cleanup) {
cleanup();
}
}
}
final _expando = Expando<SignalsContext>();
extension WatchUtils<T> on ReadonlySignal<T> {
T watch(BuildContext context) {
final ctx = _expando[this] ??= SignalsContext(context);
ctx.add(this);
return value;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment