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 &lt;Show&gt;, &lt;For&gt;, and &lt;Suspense&gt;. Resuma maps these to Rust control flow plus streaming loaders and load boundaries.