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

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));
MemberMeaning
Add, AddRange, Insert, Remove, RemoveAt, ClearAs 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, CountReading; records a dependency
void NotifyChanged()Tells readers after you changed an item's own fields
int VersionGoes 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.

MemberMeaning
T ValueReading 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 NameA name for debugging

Reactive

MemberMeaning
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 IsTrackingWhether a read would be recorded now
static int PendingEffectsHow many effects wait for the flush

Notes