Suspense and Async Rendering
waterui::widget::Suspense bridges async work and declarative views. Wrap any async
builder and Suspense takes care of launching the future, showing a placeholder, cancelling the task
when the view disappears, and re-rendering once data arrives.
Basic Usage
#![allow(unused)]
fn main() {
use waterui::prelude::*;
use waterui::widget::Suspense;
async fn load_profile() -> impl View {
text("Ada Lovelace")
}
pub fn profile() -> impl View {
Suspense::new(load_profile())
.loading(|| text("Loading profile…"))
}
}
Suspense::new(future)starts the future on first render..loading(|| …)provides a custom placeholder. If omitted, Suspense looks forDefaultLoadingViewin the environment.- The async builder receives a cloned
Environment, so it can read services or locale info during loading.
Default Loading View
Install a global placeholder so every Suspense shares the same skeleton:
#![allow(unused)]
fn main() {
use waterui::prelude::*;
use waterui::widget::suspense::DefaultLoadingView;
let env = Environment::new().with(DefaultLoadingView::new(|| text("Please wait…")));
}
Wrap your root view with .with_env(env) and all suspense boundaries inherit it.
Caching Results
Suspense rebuilds the future whenever the view is reconstructed. Cache results in bindings if you need persistence:
#![allow(unused)]
fn main() {
let user = binding(None);
fn user_view(user: Binding<Option<User>>) -> impl View {
when(user.map(|u| u.is_some()), || profile_body(user.clone()))
.or(|| Suspense::new(fetch_user(user.clone())))
}
}
fetch_user updates the binding when the network request resolves; the when branch takes over and
the placeholder disappears.
Error Handling
Wrap async results in Result and convert errors into ErrorView:
#![allow(unused)]
fn main() {
use waterui::prelude::*;
use waterui::widget::error::Error;
Suspense::new(async {
match fetch_feed().await {
Ok(posts) => feed(posts).anyview(),
Err(err) => Error::new(err).anyview(),
}
})
}
You can also stack Suspense boundaries—an outer one fetching user data, an inner one fetching related content—to keep parts of the UI responsive.
Cancellation and Restart
Dropping a Suspense (e.g., navigating away) cancels the running future. Re-rendering recreates the future from scratch. Use this to restart long-polling or subscribe/unsubscribe from streams based on visibility.
Suspense keeps async ergonomic: describe loading and loaded states declaratively, and let WaterUI handle the lifecycles.