signal()
Create a reactive value that can be read and updated.
const count = signal(initialValue, debugName?)
Parameters
| Parameter | Type | Description |
|---|---|---|
initialValue |
T |
The initial value for the signal |
debugName |
string |
Optional. Names the signal in devtools and in what_signals output; without it the signal shows up as signal_42. The what_lint hint module-scope-signal-missing-name flags module-scope signals that omit it. |
Returns
A signal object with the following methods:
| Method | Description |
|---|---|
signal() |
Read the current value (creates subscription in reactive contexts) |
signal.set(value) |
Set a new value |
signal.set(fn) |
Update based on current value |
signal(value) |
Callable write form, equivalent to signal.set(value) |
signal(fn) |
Callable update form, equivalent to signal.set(fn) |
signal.peek() |
Read value without creating a subscription |
signal.subscribe(fn) |
Run fn(value) immediately with the current value, then again on every change. Returns an unsubscribe function. |
Usage
Basic Usage
import { signal } from 'what-framework';
const count = signal(0);
// Read
console.log(count()); // 0
// Update
count.set(5);
console.log(count()); // 5
// Update with function
count.set(c => c + 1);
console.log(count()); // 6
In Components
Pass a thunk ({() => ...}) for anything that has to stay live. A bare
{count()} is only reactive when what-compiler runs, because the compiler
rewrites it to () => count(). On the automatic JSX runtime or with
hand-written h() it is read once when the component runs and never
updates. The thunk form works on every path.
function Counter() {
const count = signal(0, 'count');
return (
<button onClick={() => count.set(c => c + 1)}>
{() => `Count: ${count()}`}
</button>
);
}
With Objects
const user = signal({ name: 'Alice', age: 25 });
// Update - must create new reference
user.set(u => ({ ...u, age: 26 }));
With Arrays
const items = signal([1, 2, 3]);
// Add item
items.set(arr => [...arr, 4]);
// Remove item
items.set(arr => arr.filter(x => x !== 2));
Reading Without Subscribing
import { signal, effect } from 'what-framework';
const count = signal(0);
const multiplier = signal(2);
effect(() => {
// Uses count but doesn't subscribe to multiplier
const result = count() * multiplier.peek();
console.log(result);
});
Notes
- Signals should not be mutated directly. Use
.set()or the callable formcount(next)to update. - In JSX, wrap the read in a thunk so the binding stays live:
{() => count()}. A bare{count()}is only rewritten into a thunk by what-compiler. - Use
peek()when you need the value but don't want to create a subscription - For derived values that depend on other signals, use computed()