Introduction
A Signal is a wrapper around a value that can notify interested consumers when that value changes. Signals can contain any value, from simple primitives to complex data structures.
A Signal's value is always read through a getter function, which allows the framework to track where the signal is used, and observe its changes.
Adopting Signals, will usually greatly simplify the design of your applications: if you have variables depending on other variables (called computed variables),
variables that mutates other time (called dynamic variables, ex: front-end framework updating the DOM), or state management (ak: store
).
In addition, using Signals to hold dynamic values is easier that managing them yourself: updating manually your computed variables requires more code and quickly becomes error-prone, where Signals handle it automatically.
Finally, they perfectly bridge the gap between imperative and reactive programming, providing a smooth transition between two paradigms: you get the best of both worlds, with a simplified syntax, consistent application, and all of it without sacrificing on performances.
Example
// create a writable signal
const counter = signal(0);
// create a computed signal
const isEven = computed(() => counter() % 2 === 0);
// computed properties are signals themselves
const color = computed(() => (isEven() ? 'red' : 'blue'));
// log the values of our signals, and log them again when either (or all) changes.
effect(() => {
console.log('counter', counter(), 'isEven', isEven(), 'color', color());
});
// create an observable triggered on a click on the window
fromEventTarget(window, 'click')(() => {
// update signal's value based on the current one
counter.update((currentValue) => currentValue + 1);
});