Switch

Component for multi-case conditional rendering that automatically updates when the expression value changes, similar to a switch statement.

Signature

function Switch<T>(
  expression: () => T,
  cases: Array<Case<T>>,
  defaultRender?: (value: T) => Node
): Node;

Parameters

  • expression: () => T - Function that returns the value to evaluate against cases

  • cases: Array<Case<T>> - Array of case objects with predicate and render functions

  • defaultRender?: (value: T) => Node - Optional function to render when no case matches

Returns

  • Node - A DOM node containing the matched case content

Type Definition

interface Case<T> {
  when: (value: T) => boolean;
  render: (value: T) => Node;
}

Example

const [status, setStatus] = createSignal<
  "idle" | "loading" | "success" | "error"
>("idle");
const [data, setData] = createSignal(null);

const template = Switch(
  status,
  [
    {
      when: (value) => value === "loading",
      render: () => html`<div class="loading">Loading...</div>`,
    },
    {
      when: (value) => value === "success",
      render: () => html`<div class="success">Data: ${data()}</div>`,
    },
    {
      when: (value) => value === "error",
      render: () => html`<div class="error">Something Went Wrong!</div>`,
    },
  ],
  (value) => html`<div class="idle">Status: ${value}</div>`
);

Advanced Usage

// Complex object matching
const [user, setUser] = createSignal<User>({ ...user, role: "admin" });

const dashboardTemplate = Switch(
  () => user().role,
  [
    {
      when: (role) => role === "super-user",
      render: () => html`<div>Super-User Panel</div>`,
    },
    {
      when: (role) => role === "admin",
      render: () => html`<div>Admin Dashboard</div>`,
    },
    {
      when: (role) => role === "user",
      render: () => html`<div>User Profile</div>`,
    },
  ],
  () => html`<div class="unauthorized">Access Denied!</div>`
);

// Without default case
const [theme, setTheme] = createSignal<"light" | "dark">("light");

const themeTemplate = Switch(theme, [
  {
    when: (value) => value === "light",
    render: () => html`<link rel="stylesheet" href="light.css" />`,
  },
  {
    when: (value) => value === "dark",
    render: () => html`<link rel="stylesheet" href="dark.css" />`,
  },
]);

Behavior

  • Evaluates cases in order, rendering the first matching case

  • Only re-renders when the expression value changes or when a different case matches

  • Provides the actual expression value to both case predicates and render functions

  • If no case matches and no default render is provided, renders an empty text node

  • Uses comment markers to track DOM insertion points

  • Automatically cleans up previous renders when switching cases

Use Cases

  • 📊 Status Management: Render different UI states (loading, success, error)

  • 🛡️ User Roles: Display role-specific content and interfaces

  • 🎨 Theme Switching: Apply different styling based on user preferences

  • Form Validation: Show different messages based on validation state

  • 🔀 Multi-step Workflows: Display different steps in a process

Performance Notes

  • Efficient case evaluation - Stops at first match

  • Minimal DOM manipulation - Only updates when the matched case changes

  • Uses Object.is() for value comparison to avoid unnecessary re-renders

  • No re-evaluation of render functions when the same case remains active

Last updated