Reactivity
Store state on the View. render reads that state to build elements. Call cx.invalidate() after a mutation so the window redraws.
#Reactive state
Keep fields on the view struct. Register listeners with cx.listener so events can mutate those fields.
struct Counter {
count: usize,
}
impl View for Counter {
fn render(&mut self, cx: &mut ViewContext<'_, Self>) -> impl IntoElement {
let increment = cx.listener("increment", |this, cx: &mut EventContext| {
this.count += 1;
cx.invalidate();
});
div()
.child(text(format!("Count: {}", self.count)))
.child(button().on_click(increment).child("Increment"))
}
}A value you copy in render is the current frame’s snapshot.
#Derived state
Compute derived values in render from the fields you already store.
let doubled = self.count * 2;
text(format!("{doubled}"))Store an expensive derivation on the view when several children need the same value in one frame.
#Effects and cleanup
Start external work from listeners or Application callbacks, and stop it when the view is dropped. Closing a window drops the view and its listeners.
impl Drop for WatcherView {
fn drop(&mut self) {
self.stop.take().map(|stop| stop());
}
}#Batched updates
Calling cx.invalidate() marks the window dirty. Multiple invalidations in one event become one render. Do not install a timer to redraw when nothing changed.
