Build · browser behavior
State, actions, and effects
Presolve uses ordinary property access backed by compiler-owned dependency and update plans. There are no signal wrappers, .value reads, runtime proxies, or authored dependency arrays.
Declare owned state
Initialize a component-owned field with state(initialValue). Read it as an ordinary field in TSX, getters, actions, and admitted effects.
import { action, Component, state } from "presolve";export class Counter extends Component {count = state(0);increment = action(() => {this.count += 1;});render() {return <button onClick={this.increment}>Count: {this.count}</button>;}}Write through actions
action(handler) creates an instance-field action with the component receiver preserved. The beta admits synchronous state operations and compiler-proven calls. Pass the action directly to a browser event whenever no argument is needed.
Parameters and local values
Typed primitive parameters and serializable local literals are admitted in the closed beta action surface. A static event closure can capture an exact value.
select = action((id: number) => {const next = id;this.selectedId = next;});return <button onClick={() => this.select(42)}>Select</button>;Async handlers, unproven captures, arbitrary object mutation, and unsupported statements fail closed. Presolve does not execute the handler through a generic reactive runtime.
Derive with a pure getter
A synchronous getter becomes a computed candidate when the compiler proves it pure. Dependencies, caching, and invalidation are derived automatically.
get remaining(): number {return this.todos.filter((todo) => !todo.done).length;}Do not call computed() in new 0.2 source. Computed getters cannot write state, invoke actions, or perform capability work.
Run a browser effect and clean it up
effect(handler) declares synchronous terminal browser work. The compiler schedules it after initial render and after an affected action batch. Returning a cleanup function ties disposal to the exact component occurrence.
syncTitle = effect(() => {document.title = `${this.remaining} remaining`;return () => {document.title = "Presolve app";};});Effects cannot mutate Presolve state or call actions/effects. On branch replacement, keyed removal, or parent teardown, cleanup runs child-first before the occurrence is released.
Execution order
- Action beginsParameters and serializable locals are assigned.
- State writes applyReads later in the same outer action see them.
- Computed values invalidateOnly compiler-derived dependents participate.
- DOM plans executeBindings and structural hosts receive exact patches.
- Effects runAffected effects execute after the completed update batch.