Action
Dispatched async operations with Idle, Loading, Ready, and Error states.
Action<I, O, E> is an explicitly dispatched async operation with
UI-observable state. Never starts on read. A second dispatch logically cancels
the first (late completions ignored via generation counter); dropping cancels
the active task.
Creating and mounting
use incular::prelude::*;
use incular::reactive::{Action, ActionState};
fn main() {
let request = Action::<u32, String, ()>::new(|value| async move {
Ok(format!("async result for {value}"))
});
let count = Signal::new(0u32);
let app = Application::new(move |_cx| {
let label = match request.state() {
ActionState::Idle => "Press go".to_string(),
ActionState::Loading => "Working…".to_string(),
ActionState::Ready(value) => value,
ActionState::Error(_) => "Failed".to_string(),
};
let tap_count = count.clone();
let staring = request.clone();
Container::builder()
.padding(EdgeInsets::all(24.0))
.alignment(Alignment::CENTER)
.child(
GestureDetector::new(Text::new(label)).on_tap(move || {
tap_count.update(|c| *c += 1);
staring
.dispatch(tap_count.get())
.expect("dispatch action");
}),
)
.build()
.into()
})
.expect("valid application");
incular::run(app).expect("run application");
}Bounds: input I: 'static, output O: Clone + Send, error E: Clone + Send,
operation returns Future<Output = Result<O, E>> + Send.
Dispatching and reading
state() mounts and reads tracked state; state_signal() returns the
underlying signal. dispatch(input) sets Loading and spawns via the owner
scope (Err(NotMounted) before mount); cancel() aborts and reports
Error(Runtime(Cancelled)) — all exercised in the runnable program above.
States
| State | Meaning |
|---|---|
Idle | Initial; nothing dispatched |
Loading | Operation running |
Ready(T) | Completed with value |
Error(Operation(E)) | Operation failed |
Error(Runtime(Cancelled)) | Superseded, cancelled, or dropped |
Initial state is Idle — matched in the runnable program above.
ActionDispatchError::NotMounted when dispatched before mount or after the
scope was cancelled.