Skip to main content

Control Flow

Basics​

Since Sinho templates are only created once for the whole lifetime of a component, you can't use dynamic JavaScript expressions such as ternary operators in the template. Instead, you can use special control flow functional components.

Conditionals​

You can use the <If>/<ElseIf>/<Else> components to conditionally render parts of the template:

import { Component, useSignal, If, ElseIf, Else } from "sinho";

class MyComponent extends Component("my-component") {
render() {
const [count, setCount] = useSignal(0);

return (
<>
<If condition={() => count() > 0}>
<p>My content</p>
<p>{count} items</p>
</If>
<ElseIf condition={() => count() < 0}>
<p>Error occurred!</p>
</ElseIf>
<Else>
<p>No content</p>
<p>
<button onclick={() => setCount(100)}>Load items</button>
</p>
</Else>
</>
);
}
}

<ElseIf>/<Else> are optional and you can have as many <ElseIf> as you want. <Else> should be the last one if it's present.

tip

Keep <If>/<ElseIf>/<Else> next to each other for easier readability and reasonability of your code.

Loops​

You can use the <For> component to loop over an array and render a template for each element:

import { Component, useSignal, For } from "sinho";

class MyColors extends Component("my-colors") {
render() {
const [colors, setColors] = useSignal(["red", "green", "blue"]);

return (
<ul>
<For each={colors}>
{(color, index) => (
<li style={{ color }}>
#{index}: {color}
</li>
)}
</For>
</ul>
);
}
}

When colors updates, <For> will compare the new array with the old one and efficiently update the DOM.

You can additionally specify a key function to help <For> identify which elements should be stable across updates. With a key function <For> can infer which correct operation to perform (insert, update, or remove) for each element across updates.

import { Component, useSignal, For } from "sinho";

class TaskList extends Component("task-list") {
render() {
const [tasks, setTasks] = useSignal([
{ id: 1, text: "Learn Sinho" },
{ id: 2, text: "Build an app" },
]);

return (
<ul>
<For each={tasks} key={(task) => task.id}>
{(task, i, arr) => (
<li>
#{() => i() + 1}/{() => arr().length}: {() => task().text}
</li>
)}
</For>
</ul>
);
}
}

If the key function is not specified, <For> will use the index of the element as the key.

warning

The key function must be a pure function that returns a unique value for each element, otherwise an error will be thrown.