Control flow
Show and Switch decide what is on the page. Only the branch that changes is built or removed.
Show the code
import { useStore } from "@shadow-js/core";
import { Match, Show, Switch } from "@shadow-js/web";
type Step = "idle" | "loading" | "done";
export function Steps() {
const [step, setStep] = useStore<Step>("idle");
return (
<div class="stack">
<div class="row">
{(["idle", "loading", "done"] as const).map((name) => (
<button type="button" aria-pressed={step() === name} onClick={() => setStep(name)}>
{name === "idle" ? "Idle" : name === "loading" ? "Loading" : "Done"}
</button>
))}
</div>
<Switch fallback={<p>Nothing has happened yet.</p>}>
<Match when={step() === "loading"}>
<p>Fetching.</p>
</Match>
<Match when={step() === "done"}>
<p>Finished.</p>
</Match>
</Switch>
<Show when={step() !== "idle"}>
<p>Not idle any more.</p>
</Show>
</div>
);
}
Show renders its children while when is truthy and its fallback otherwise. Switch renders the first Match whose when is truthy, or its fallback. A branch is created when it is first shown, not before, and when it goes away its effects stop, its onCleanup callbacks run and its DOM is removed. While a branch stays shown, its own bindings update it in place.
Truthy means JavaScript truthy#
0, "", NaN, null, undefined and false are falsy. Everything else is truthy, [] and {} included. So <Show when={items.length}> hides the list when it is empty, and <Show when={user}> shows it for any object.
A branch that needs the value#
A function as the child receives an accessor of the truthy value, so you do not need a non-null assertion:
Show the code
import { useStore } from "@shadow-js/core";
import { Show } from "@shadow-js/web";
export function Greeting() {
const [session] = useStore<{ user: { name: string } | null }>({ user: { name: "Ada" } });
return <Show when={session.user}>{(current) => <p>Hello {current().name}</p>}</Show>;
}
A ternary or && in JSX is compiled the same way: it rebuilds only when the condition flips.
Go deeper#
Control flow also covers Dynamic, Portal, lazy components, keyed children and exactly what each component rebuilds.