Conditions: Show
Conditional rendering means showing different markup depending on the data: a "No tasks" message for an empty list, a "Log out" button only for a signed-in user. Solid has a built-in component for this, Show.
Show
Show renders its content when the condition in the when attribute is truthy:
// src/components/TodoHint.jsx
import { createSignal, Show } from 'solid-js';
export default function TodoHint() {
const [visible, setVisible] = createSignal(false);
return (
<div>
<button onClick={() => setVisible(!visible())}>Hint</button>
<Show when={visible()}>
<p>Click a task to mark it as done.</p>
</Show>
</div>
);
}Each click on the button shows or hides the paragraph. When the condition is false, the paragraph is not in the DOM at all.
fallback
The fallback attribute sets what to show when the condition is false:
// src/components/TodoSummary.jsx
import { Show } from 'solid-js';
export default function TodoSummary(props) {
return (
<Show when={props.count > 0} fallback={<p>No tasks</p>}>
<p>Tasks in the list: {props.count}</p>
</Show>
);
}Usage: <TodoSummary count={todos().length} />. For an empty list you see "No tasks", otherwise the number of tasks.
The value inside Show
If you pass an object to when, the content can be written as a function. It receives that value as a getter function, and the value is guaranteed not to be empty:
// src/components/Profile.jsx
import { createSignal, Show } from 'solid-js';
export default function Profile() {
const [user, setUser] = createSignal(null);
return (
<div>
<Show when={user()} fallback={<button onClick={() => setUser({ name: 'Anna' })}>Log in</button>}>
{(u) => <p>Hello, {u().name}</p>}
</Show>
</div>
);
}Before the click you see the "Log in" button, after it the greeting "Hello, Anna".
Why not the ternary operator
| Code | Works? |
|---|---|
{visible() ? <p>Yes</p> : null} | Yes, for simple cases |
{visible() && <p>Yes</p>} | Yes |
<Show when={visible()}> | Yes, recommended |
The ternary operator and && are reactive in Solid too. Show reads better, supports fallback and does not recreate its content when the condition changes from one truthy value to another.
Common mistake
Putting an early return with a condition in the component body:
// src/components/TodoSummary.jsx
export default function TodoSummary(props) {
// Wrong: the check runs only once
if (props.count === 0) return <p>No tasks</p>;
return <p>Tasks in the list: {props.count}</p>;
}The component body runs once, so the markup is chosen for good at creation time. Move conditions that can change into JSX with Show.