Control Flow

In Retend, you use special functions—If, For, and Switch—to handle conditionals and lists in your user interface. These functions connect directly to your Cells, so when your data changes, your layout updates automatically.

Conditional Rendering with If

When you want to show or hide parts of your interface based on a condition, use the If function.

It takes a Cell (or any regular value) and branches based on whether the value is true or false.

import { If, Cell } from 'retend';

function ToggleMessage() {
  const show = Cell.source(false);
  const toggle = () => show.set(!show.get());

  return (
    <div>
      <button type="button" onClick={toggle}>
        Toggle Message
      </button>

      {If(show, {
        true: () => <p>The message is visible!</p>,
        false: () => <p>The message is hidden.</p>,
      })}
    </div>
  );
}

If you only care about the true case, you can just provide that branch:

{
  If(show, {
    true: () => <p>Only shows when the Cell is true.</p>,
  });
}

(Note: Standard JavaScript if statements or && operators don't connect to Retend's reactivity system if the data changes later. Always use the If function for parts of your UI that can change).

Shorthand Syntax

If you only need to render something when the value is truthy, you can pass a function instead of an object:

{
  If(show, (value) => <p>The value is: {value}</p>);
}

You can also provide a third argument for the falsy case:

{
  If(
    show,
    () => <p>Visible!</p>,
    () => <p>Hidden.</p>
  );
}

Rendering Lists with For

When you have an array of data, use the For function to display a list of elements.

You provide the array, and a callback function that returns the JSX you want to render for each item.

import { For, Cell } from 'retend';

function ItemList() {
  const items = Cell.source([
    { id: 1, name: 'Apple' },
    { id: 2, name: 'Banana' },
  ]);

  return (
    <ul>
      {For(
        items,
        (item, index) => (
          <li>
            Item {index}: {item.name}
          </li>
        ),
        { key: 'id' }
      )}
    </ul>
  );
}

(Note: The index parameter is a reactive Cell<number>, not a plain number. You can pass it directly into JSX and it will update automatically, but if you need to use it in a calculation, call index.get() first.)

Using Keys for Efficiency

When rendering a list of objects that might change (like adding or removing items), it's highly recommended to provide a key in the options object at the end.

The key tells Retend how to uniquely identify each item, which makes updating the list much faster. You can provide the name of the unique ID property as a string, like key: 'id'.

Multi-State Rendering with Switch

When you have more than two possible states—like checking whether data is "loading", "success", or "error"—nested If functions can get messy. The Switch function handles this cleanly.

import { Switch, Cell } from 'retend';

function DataFetcher() {
  const status = Cell.source('loading');

  return (
    <div>
      {Switch(status, {
        loading: () => <p>Fetching data...</p>,
        success: () => <p>Success!</p>,
        error: () => <p>Something went wrong.</p>,
      })}
    </div>
  );
}

Switch looks at the value inside your Cell and runs the matching branch. If the status is "success", it only renders the success branch.

Default Case

If the value might not match any of the defined branches, you can pass a third argument as a fallback:

{
  Switch(
    status,
    {
      loading: () => <p>Loading...</p>,
      success: () => <p>Done!</p>,
    },
    (value) => <p>Unknown status: {value}</p>
  );
}

By using If, For, and Switch, you ensure your layouts stay in sync with your data automatically.