<Show>
Conditional rendering component. Renders children when a condition is truthy, otherwise renders an optional fallback.
<Show when={condition} fallback={alternative}>
{children}
</Show>
Props
| Prop | Type | Description |
|---|---|---|
when |
T | (() => T) |
The condition to evaluate. Children render when this is truthy. A thunk (when={() => user()}) or an expression (when={items().length > 0}) is always safe. The compiler calls a bare identifier as an accessor when it can tell the name is a signal (a local initialised by signal(), a destructured prop, or an import), so when={flag} throws if such a name holds a plain value; a property access is not called, so when={props.user} tests the function object and stays permanently truthy. |
fallback |
Element | null |
Optional. What to render when when is falsy. Defaults to null (renders nothing). |
children |
Element | Element[] |
The content to render when when is truthy. |
Returns
A reactive region, not a value you handle yourself. Show returns a thunk that the renderer installs as a fine-grained effect; each time the effect runs it yields children if when is truthy and fallback (or null) if it is falsy, and the previous branch is disposed.
Usage
Basic Conditional
import { Show, signal } from 'what-framework';
const isLoggedIn = signal(false);
<Show when={isLoggedIn} fallback={<p>Please log in</p>}>
<p>Welcome back!</p>
</Show>
With a Signal Value
const user = signal(null);
<Show when={user} fallback={<LoginForm />}>
<Dashboard />
</Show>
// When user is set, Dashboard renders
user.set({ name: 'Alice' });
Without Fallback
const showHint = signal(false);
<Show when={showHint}>
<p className="hint">Press Enter to submit</p>
</Show>
In a Component
function UserProfile({ user }) {
return (
<div>
<Show when={user} fallback={<p>No user found</p>}>
<h2>{() => user()?.name}</h2>
<p>{() => user()?.email}</p>
</Show>
</div>
);
}
user here is a signal passed down as a prop, which is what lets the compiler call it. The ?. is not what makes the first render work: the branch is not built at all while user is null. It earns its place on the way back out, when the branch closes again (see below).
How It Works
Uncompiled (plain h() or the automatic JSX runtime), Show runs as an ordinary component and returns a reactive thunk. The renderer installs that thunk as a fine-grained region, and every time the region re-runs it reads when, calling it first if it is a function, and yields children or fallback. The region is reactive on its own; it does not need to be wrapped in anything.
Compiled, Show is never called at all. The babel plugin erases the tag and emits the same conditional thunk inline, with the condition behind a memo so only a change in truthiness rebuilds the branch. The uncompiled region has no such memo and re-runs on every write to the condition signal.
Children are lazy on both paths. Nothing in the branch is constructed and no binding inside it runs until when is truthy, so <Show when={user}><h2>{() => user().name}</h2></Show> renders the fallback instead of throwing while user is null. That holds for a plain element child and for a component child alike, and closing the branch removes it again: onCleanup in a component child fires on the swap.
Where the two paths still differ is that swap back. Compiled, a binding that belonged to a branch which has closed can re-run when the condition changes again, and an unguarded read of the value that has just gone away prints [what] Uncaught error in effect during update. The rendered DOM is correct either way, so this is console noise rather than a broken screen, and writing user()?.name removes it.
Notes
Showis a convenience component. You can achieve the same result with a ternary expression:{() => condition() ? <A/> : <B/>}.- Uncompiled, the
whenprop accepts a signal, a thunk or a plain value. Compiled, a bare identifier the compiler reads as a signal name is called, so a plain value passed that way throws; pass a thunk when the value might not be a function. - For multiple conditions, use
<Switch>and<Match>instead of nested<Show>components. - When
whenis falsy and nofallbackis provided, nothing is rendered. - The compiler requires a
whenprop:<Show>without one fails the build. The message names the file and prints a code frame at the offending tag, wherever it appears in the file:SyntaxError: src/Nested.jsx: <Show> requires a "when" prop. Example: <Show when={isOpen} fallback={null}>...</Show> 6 | <section> > 7 | <Show> | ^ 8 | <p>hi</p><Switch>refuses the same way, with its own text, when an arm is missing awhenprop or when the arms cannot be read statically.