State and recomposition
State<T> is a copyable handle to an observable value owned by the current component scope.
Reading the value during composition subscribes that scope; writing a different value requests local recomposition.
Declare state in a scope
Section titled “Declare state in a scope”[[huxerui::scope]]View Counter() { auto count = UseState(0);
return Column { Text::Format("Count: {}", count), Button("Increment").OnClick([count] { count += 1; }), }.With(Spacing(12.0F));}[[huxerui::scope]] is transformed at build time.
Use it when a reusable component owns local state, calls UseEvents, or needs an independent recomposition boundary.
The application root already owns a scope and must not be annotated.
Read naturally
Section titled “Read naturally”State<T> converts to const T&, so ordinary expressions read the current value and register the same observation as Get():
auto expanded = UseState(false);auto profile = UseState(Profile{});
if (expanded) { ShowDetails();}
Text(profile->display_name)Prefer the conversion or operator-> when the surrounding C++ expression already makes the value type clear.
Get() remains available when an explicit reference is useful or overload resolution would otherwise be ambiguous; it is not the default spelling for routine reads.
Text and many controlled components accept State<T> directly:
Text(count)Switch("Notifications", enabled)Slider(volume).Range(0.0F, 100.0F)Passing a state handle reads its current value. It does not transfer ownership or install an implicit write-back handler.
Update through the handle
Section titled “Update through the handle”Assignment and the supported C++ operators publish a new authoritative value:
count = 10;count += 2;++count;enabled = !enabled;Use Update for an in-place mutation that should become one observed update:
profile.Update([](Profile& value) { value.display_name = "Ada"; value.signed_in = true;});For equality-comparable values, assigning an equal value does not notify subscribers.
Controlled components
Section titled “Controlled components”User-owned values remain authoritative in application state. A component renders the current value and emits a requested next value:
[[huxerui::scope]]View Settings() { auto enabled = UseState(false);
return Switch("Notifications", enabled) .OnChanged([enabled](bool next) { enabled = next; });}Checkboxes, radio buttons, switches, sliders, tabs, segmented buttons, text editing values, navigation selection, progress, and declarative visibility follow this model. Always feed an accepted event value back into a later composition; the component does not mutate application state on its own.
Observable lists
Section titled “Observable lists”UseStateList<T> owns a vector-like collection whose structural operations notify the declaring scope:
auto items = UseStateList<Item>({ {1, "Alpha"}, {2, "Bravo"},});
items.PushBack({3, "Charlie"});items.Insert(1, {4, "Delta"});items.Set(0, {1, "Updated"});items.Move(2, 0);items.Erase(1);It also provides Size, Empty, At, operator[], const iteration, PopBack, and Clear.
Use Update(index, function) when one stored value needs an in-place mutation.
Preserve state identity
Section titled “Preserve state identity”State identity is the current composition scope, the UseState source location, and the occurrence at that location.
Keep state calls structurally stable within a component.
Unkeyed siblings reconcile by position. Give dynamic stateful children stable semantic keys when entries can be inserted, removed, or reordered:
Column { ForEach(items, [](const Item& item) { return ItemRow(item).Key(item.id); }),}Keys must be unique among siblings under the same parent. They accept integral values, enums, strings, string views, and string literals.
Recomposition stays local
Section titled “Recomposition stays local”Only scopes that read a changed state are invalidated. Recomposition creates new transient declarations, then reconciliation updates compatible mounted nodes and replaces incompatible ones.
Hover, press, focus, momentum, caret blink, and active animation are retained runtime facts.
They do not need application State and do not force component recomposition every frame.
Capture handles by value
Section titled “Capture handles by value”State<T> and StateList<T> are shared handles.
Capture them by value in event handlers and task continuations:
Button("Clear").OnClick([items] { items.Clear();})An empty default-constructed handle is invalid.
Obtain application state through UseState or UseStateList inside a valid scope.
See Scope, Composition and identity, and the State API.

