Control flow & iteration
Use Rust if / match for static branches, reactive <Show> / <Match>, and keyed <For> for lists bound to signals.
LIVE
<Show> toggle
Welcome back!
Sign in to continue
Conditional UI
Use Rust if / match, or the <Show> helper (Leptos-style):
let logged_in = 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 = 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
For static SSR lists, use .iter().map(). For reactive lists, use <For>:
let items = signal(vec!["Rust", "Resuma", "Flow"]);
view! {
<ul>
<For each={items} let:label>
<li>{label.clone()}</li>
</For>
</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.