API reference
Reactivity
Components are reactive through signals: a value that knows who read it. In a component you write [State] and never see them. This page is for the cases where you use the runtime directly. Namespace: DevCore.UiEngine.Reactivity.
How it works
- Reading a
[State]value inside a template expression, a[Derived]or an[Effect]records a dependency. - Assigning it marks its readers dirty. Nothing else happens yet.
- Once per frame the runtime flushes: every dirty reader runs once, however many values changed.
There is no virtual DOM and no diffing: the compiler wrote, for each binding, the code that updates exactly that text, attribute or style.
Reactive plain classes
Outside components, mark fields of a partial class with [State]; the source generator adds a reactive property for each.
public partial class PlayerState
{
[State] int gold; // property Gold
[State] float health; // property Health
}
player.Gold += 50; // every screen that shows it updates this frame
Collections
StateList<T> is a list that {#each} and {#virtual} follow.
using DevCore.UiEngine.Reactivity;
public StateList<ShopItem> items = new StateList<ShopItem>();
items.Add(sword);
items.Move(0, 3);
items.Sort((a, b) => a.Price.CompareTo(b.Price));
| Member | Meaning |
|---|---|
Add, AddRange, Insert, Remove, RemoveAt, Clear | As List<T>; each notifies readers |
void Move(int from, int to) | Moves an item; a keyed list moves its row |
void Sort(Comparison<T> comparison) | Sorts in place |
IndexOf, Contains, the indexer, Count | Reading; records a dependency |
void NotifyChanged() | Tells readers after you changed an item's own fields |
int Version | Goes up with every change |
StateDictionary<K, V> is the same idea for a dictionary. Enumerating a StateList with foreach allocates nothing.
Signal<T>
What a [State] field compiles to. Use one directly when state lives outside any class the generator can extend.
| Member | Meaning |
|---|---|
T Value | Reading records a dependency; assigning notifies readers when the value changed |
T Peek() | Reads without recording a dependency |
void Set(T value) | Assigns |
void Notify() | Notifies readers although the reference did not change (a mutated object) |
string Name | A name for debugging |
Reactive
| Member | Meaning |
|---|---|
static void Update() | The once-per-frame update: ticks, then the flush. UiSystem calls it; tests call it before View.Update() |
static void Flush() | Runs pending effects now |
static T Untrack<T>(Func<T> read) | Reads without recording dependencies |
static UntrackedScope Untracked() | The same for a block: using (Reactive.Untracked()) { … } |
static bool IsTracking | Whether a read would be recorded now |
static int PendingEffects | How many effects wait for the flush |
Notes
- Prefer
[State]to raw signals in components: it reads like plain C# and compiles to the same thing. - An effect that writes state it also reads runs again; the runtime guards against endless loops.
- Reactivity runs on the main thread.