Ramonda

as and render

list() takes exactly one of them.

as — the item is a component

list({ each: this.tasks, as: TaskRow })

It builds <TaskRow item={task} /> for each item. The component receives the item as its item prop:

@Host("li")
class TaskRow extends Component<{ item: Task }> {
  render() {
    return <span>{this.props.item.title}</span>;
  }
}

There is no per-item function in your code. Nothing to memoize, nothing that gets recreated on every render, nothing for a lint rule to flag.

render — the item is plain markup

list({
  each: this.tags,
  render: (tag) => <span className="chip">{tag.label}</span>,
})

Use it when an item maps to bare markup and a whole component would be ceremony. The result is a plain element — no <ramonda-host> wrapper appears.

Which

the item has state, lifecycle, or handlers of its own as
the item is a few tags render

If you find yourself writing a render closure that captures a lot of the owner's state, that is usually the signal to make it a component and switch to as.

One or the other, never both

The types forbid passing both, and forbid passing neither. At runtime the same mistake is reported as RMD014 — for the case where the build has no types.

What as does not do

It does not reduce the number of render calls. A fresh vnode is still built per item when the owner re-renders; as removes the closure, not the work.

Reducing the calls is a different mechanism — per-item reactive scopes, so an item whose data did not change is not re-rendered at all. That machinery is always on, and it is what makes a large list cost work proportional to what changed rather than to its length.

Next