implement
Implement/Control flow/ForEach

In almost every application you will find a need to render dynamic list data.

In React this is a bit easier you just call .map() on your state and your list will update. However in implement this will render your list but the list will never update when your state changes.

// ⚠️ THIS WILL NEVER UPDATE
...todos.get().map((todo) => Li(todo.title))

This makes map a fine solution when you want to render a static list but useless for dynamic data. For dynamic data you need to use the ForEach component.

ForEach accepts an Signal<T[]>, a function to get a key, and finally a function to create it's children.

ForEach(
	items,
	(item) => item.id, // key must be unique!
	(item, index) => Item(item, index),
);

Try using ForEach to render the Todos in this Todo app example.

TIP

You can use todo.bind('title') to reactively bind to the title of a todo within the ForEach.

index.ts
import { Button, Div, ForEach, Form, H1, Input, Li, signal, Ul } from "@implementjs/core";

export default function App() {
	const search = signal("");
	const todos = signal([
		{ id: 1, title: "Read the docs" },
		{ id: 2, title: "Write a component" },
		{ id: 3, title: "Ship it" },
	]);

	function addTodo(e: SubmitEvent) {
		e.preventDefault();
		const title = search.get();
		if (title === "") return;
		todos.push({ id: todos.get().length + 1, title });
		search.set("");
	}

	return Div(
		H1("ForEach"),
		Form(
			{ onSubmit: addTodo, class: "flex gap-2" },
			Input({ value: search, placeholder: "What do you need to do..." }),
			Button({ type: "submit" }, "Add"),
		),
		Ul(
			// ⚠️ THIS WILL NEVER UPDATE
			...todos.get().map((todo) => Li(todo.title)),
		),
	);
}
Preview