Core concepts
State
Signals, memos and bindings drive fine-grained updates without a virtual DOM.
component runs its closure once to build the view. The closure never runs again. Updates happen
because a property reads a signal inside bind, so only that property changes when the signal
changes.
Signals
cx.signal(value)creates aSignal<T>. Read it withget,withorwith2. Write it withsetorupdate.cx.memo(..)derives a value and recomputes only when its inputs change.bind(move |rt| ..)turns any expression into a reactive property.
Any property accepts a literal, a Signal, a Memo or a bind.
let count = cx.signal(0);
text(bind(move |rt| format!("Count: {}", count.get(rt))))Read first, then write
Because Cx derefs to the runtime, reads and writes both need &mut. Read the value into a local
first, then write.
let initial = todo.with(cx, |todo| todo.done);
let done = cx.signal(initial);Lists and structure
show
show(condition, then, otherwise) mounts one of two branches and unmounts the hidden one.
for_each
for_each(items, key, row) renders a keyed list and gives each row its own signal.
lazy_for_each and lazy_vstack
Mount only the visible rows of a long list.
keyed and error_boundary
keyed(..) rebuilds a branch when a derived value changes. error_boundary(..) catches a
panicking component and shows a fallback.
Async work
With the default tokio feature, cx.spawn(future, on_done) runs a future off the UI thread and
calls on_done with its result back on the UI thread.