Lightweight, zero-dependency, signals primitives implemented in ReScript for fine-grained reactivity.
npm install rescript-signalsAdd to your rescript.json:
{
"dependencies": ["rescript-signals"]
}Signals are reactive containers for values that notify dependents when changed.
open Signals
// Create a signal
let count = Signal.make(0)
// Get the value (with tracking)
let value = Signal.get(count)
// Get the value (without tracking)
let value = Signal.peek(count)
// Set a new value
Signal.set(count, 1)
// Update with a function
Signal.update(count, n => n + 1)
// Custom equality function
let signal = Signal.make(0, ~equals=(a, b) => a == b)
// Named signal for debugging
let signal = Signal.make(0, ~name="counter")Computed signals automatically update when their dependencies change.
open Signals
let count = Signal.make(5)
let doubled = Computed.make(() => Signal.get(count) * 2)
Console.log(Signal.peek(doubled)) // 10
Signal.set(count, 10)
Console.log(Signal.peek(doubled)) // 20
// Dispose when no longer needed
Computed.dispose(doubled)Effects run side effects in response to signal changes.
open Signals
let count = Signal.make(0)
// Effect runs immediately and on signal changes
let disposer = Effect.run(() => {
Console.log(`Count is: ${Int.toString(Signal.get(count))}`)
None // or Some(cleanupFunction)
})
Signal.set(count, 1) // Logs: "Count is: 1"
// Dispose when done
disposer.dispose()open Signals
let url = Signal.make("/api/data")
let disposer = Effect.run(() => {
let currentUrl = Signal.get(url)
// Start fetch
fetchData(currentUrl)
// Return cleanup function
Some(() => {
Console.log("Cleaning up previous fetch")
cancelFetch(currentUrl)
})
})
// Cleanup runs before re-executing and on disposal
Signal.set(url, "/api/other")
disposer.dispose()- Signals: Reactive state containers
- Computed: Derived reactive values
- Effects: Side effects with automatic cleanup
- Dependency Tracking: Automatic tracking of signal dependencies
- Fine-grained Reactivity: Only affected computations re-run
- Type-safe: Full ReScript type safety
type t<'a>
let make: ('a, ~name: option<string>=?, ~equals: option<('a, 'a) => bool>=?) => t<'a>
let get: t<'a> => 'a
let peek: t<'a> => 'a
let set: (t<'a>, 'a) => unit
let update: (t<'a>, 'a => 'a) => unitlet make: (unit => 'a) => Signal.t<'a>
let dispose: Signal.t<'a> => unittype disposer = {dispose: unit => unit}
let run: (unit => option<unit => unit>) => disposerSee CONTRIBUTING.md for development setup and guidelines.
npm testnpm run buildnpm run watchSee LICENSE for details.