Overview
Build reactive state for .NET: update a value, and the computations that depend on it update too.
- Signals hold values you can read and write.
- Memos derive values from tracked reads.
- Effects run when a value they read changes.
A taste
open Ranvier
let graph = new Graph ()
let doubled =
graph.Run (fun () ->
let count = createSignal 1
let doubled = createMemo (fun _ -> count.Value * 2)
createEffect (fun () -> printfn "doubled = %d" doubled.Value)
count.Value <- 5
doubled)
doubled = 2
doubled = 10
What you get
Targets
net10.0, net8.0 and netstandard2.1 and Fable (JavaScript).
Guide
- Installation: preview packages, supported targets and Native AOT.
- Getting started: a short walkthrough of a reactive graph.
- Graphs, Signals, Memos and Effects: the core primitives.
- Roots and owners, Cleanup, Untrack and Batch: lifetime and tracking controls.
- Editable values and Drafts: local edits over upstream state.
- Async and pending: in-flight values, async memos, boundaries, and threading.
- Testing async state: deterministic tests that decide when each flight lands.
- Blazor Server: one graph per circuit, with
ThreadAffinity.Serialised. - Collections: an overview linking to projections, lookups, selectors and collection views.
- Aggregates: totals, counts and folds over collection rows.
- Forms: records of reactive fields and batched resets.
- Tracing: why a node ran or did not run, where it was created, and the graph as it stands.
- Signal maps: how to read the live graph maps beneath the examples, and how to write one.
- Troubleshooting: each exception message and common symptom, with its cause and fix.
- Migrating from Elmish: an MVU model read through selector memos, one view at a time.
- C#: C# factories, XAML bindings and reactive commands.
Status
Implementation status and planned features
| Area | Status |
|---|---|
| Core graph (signal, memo, effect, owners, batching) | Implemented and tested. |
| Async and boundaries | Implemented. A pending .Value read throws NotReadyException; TryValue reads without throwing. |
| Projections, lookups and selectors | Implemented, with factory map semantics. A node created inside a memo pulled by a projection row belongs to that memo. |
| Fable/JavaScript | Implemented and tested under Node.js; no package published yet. See Fable (JavaScript) target. |
Collection combinators (Projection.filter, choose, map, mapWith, sortBy, groupBy) | Implemented and tested, including pending and error behaviour; see Collections. |
Editable values (createEditable, createDraft) and the MVU bridge (Mvu, in the Ranvier.Elmish package) | Implemented and tested; see Editable values and forms and Migrating from Elmish. |
| Reusable lens and prism values for deep writes | Not implemented; they wait on a need for reusable focus paths over collections. |