Control flow & iteration

Use Rust if / match for static branches, reactive <Show> / <Match>, and keyed <For> for lists bound to signals.

LIVE

<Show> toggle

Conditional UI

Use Rust if / match, or the &lt;Show&gt; 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 &lt;For&gt;:

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