Control flow & iteration
Resuma uses plain Rust inside view! — no separate <Show> / <For> components. That keeps templates predictable and fully type-checked.
Conditional UI
Use Rust if / match, or the <Show> helper (Leptos-style):
let logged_in = use_signal(false);
view! {
<>
<Show when={logged_in.get()}>
<p>"Welcome back!"</p>
</Show>
<Show when={!logged_in.get()} fallback={view! { <a href="/login">"Sign in"</a> }}>
<span></span>
</Show>
</>
}Match on enums
enum Tab { Docs, Examples }
let tab = use_signal(Tab::Docs);
view! {
<nav>
{match tab.get() {
Tab::Docs => view! { <span class="active">"Docs"</span> },
Tab::Examples => view! { <span class="active">"Examples"</span> },
}}
</nav>
}Lists and iteration
let items = use_signal(vec!["Rust", "Resuma", "Flow"]);
view! {
<ul>
{items.get().iter().map(|label| {
view! { <li>{label.to_string()}</li> }
}).collect::<Vec<_>>()}
</ul>
}Loaders and boundaries
For async data, prefer load_boundary over manual match use_*_load() when you want explicit pending/error UI:
load_boundary(
use_items_load(),
|items| view! { <ul>{/* render items */}</ul> },
|err| view! { <p class="error">{err.message.clone()}</p> },
|| view! { <p>"Loading…"</p> },
)vs Leptos
Leptos provides <Show>, <For>, and <Suspense>. Resuma maps these to Rust control flow plus streaming loaders and load boundaries.