Reactive
All-around state engine with signals and fine-grained updates.
One small package for every kind of state. A signal stores a value. A derived value follows it. A record gives state a shape. A reducer gives every change an action. All of them share one subscription model, so learning one teaches you the rest.
Framework agnostic, typed end to end, and small enough to use for a single field.
Start Here
Core Ideas
- Fine-grained updates. Subscribers hear about a value only when that value changes.
- Two signal styles. Event based and closure based, used together in the same app.
- Explicit state shapes. Arrays, maps, booleans, finite state machines, reducers and records.
- Action-driven changes. Put writes behind
dispatchor an@actionmethod when a value has rules. - Batching built in. Group writes and notify once with the final values.
- Lazy derivations. A derived value attaches to its source only while someone observes it.
Quick Peek
import { State, StateArray } from "@denshya/reactive"
const blog = {
articles: new StateArray([{ title: "Hello" }]),
user: new State({ name: "me" })
}
blog.articles.subscribe(articles => console.log(articles))
blog.user.$.name.subscribe(name => console.log(name))
blog.articles.push({ title: "Second post" })
blog.user.$.name.set("you")
import { StateReducer, StateRecord, local, action } from "@denshya/reactive"
const counter = StateReducer.fromHandlers<number, { type: "increment" }>(0, {
increment: state => state + 1
})
class Settings extends StateRecord {
@local accessor theme = "light"
@action toggleTheme() {
this.theme = this.theme === "light" ? "dark" : "light"
}
}
Install
bun add @denshya/reactive
npm install @denshya/reactive
License
MIT