Lists
You can use <ForEach> component to render reactive lists. When items are added, removed, or reordered, only the affected DOM nodes change.
Basic Usage
<ul>
<ForEach
each={() => items.get().iter()}
key={(item) => item}
children={(item) => {
<li>{ () => item }</li>
}}
/>
</ul>
Three attributes:
- each: a function returning an iterator
- key: maps each item to a unique identifier
- children: render function that converts each item to a view
Todo Example
fn todo_app() -> &View {
let (input_val, set_input_val) = @reactive.create_signal("")
let (todo, set_todo) = @reactive.create_signal(["Example."])
let add_item = _ => {
let text = input_val.get()
if text != "" {
set_todo.set(todo.get() + [text])
}
set_input_val.set("")
}
let remove_item = item => {
let new_list = todo.get().filter(fn(t) { t != item })
set_todo.set(new_list)
}
<div>
<h1> Todo List </h1>
<div>{() => todo.get().length().to_string() }</div>
<div>
<input
type="text"
value={input_val}
on:input={ev => set_input_val.set(event_target_value(ev))}
/>
<button on:click={add_item}> Add </button>
</div>
<ul>
<ForEach
each={()=>todo.get().iter()}
key={(x)=>{return x}}
children={(item) => {
<li>
{() => item}
<button on:click={_ => remove_item(item)}> "Delete" </button>
</li>
}}
/>
</ul>
</div>
}
Keyed Updates
Items are tracked by their key, not their index. This means:
- Adding an item at the start doesn’t re-render existing items
- Removing an item only removes its DOM node
- Reordering only moves DOM nodes without recreating them
How It Works
When the data array changes, Aitne computes the difference between the old and new key sets. It then applies only the necessary DOM changes — insertions, removals, and moves — directly, without touching unchanged nodes.