List rendering artinya menggambar satu baris markup untuk setiap item di sebuah array. Di Svelte caranya pakai blok {#each}. Bayangin papan menu Warung Bu Sri. Bu Sri gak menulis tiap baris dengan tangan. Dia punya satu cetakan baris "nama, harga", lalu mencetaknya sekali untuk tiap menu di buku catatannya. Tambah satu menu di buku, papannya ikut bertambah satu baris. {#each} adalah cetakan itu, dan array adalah buku catatannya.
🧪 Tebakan cepat: menu Nasi Goreng, Mie Ayam, dan Es Teh digambar dengan
{#each menu as item}, tanpa key. Tiap baris punya kolom catatan, dan pembeli menulis "pedas" di baris Nasi Goreng. Lalu baris pertama dihapus denganmenu = menu.slice(1). Catatan "pedas" ikut terhapus, atau pindah ke baris Mie Ayam? Jawabannya ada di bagian "Keyed each: (item.id)".
{#each}: satu cetakan, diulang per item
<script>
let menu = ["Nasi Goreng", "Mie Ayam", "Es Teh"]
</script>
<ul>
{#each menu as item}
<li>{item}</li>
{/each}
</ul>
Hasil di halaman:
<ul>
<li>Nasi Goreng</li>
<li>Mie Ayam</li>
<li>Es Teh</li>
</ul>
{#each menu as item}membuka perulangan atas arraymenu,{/each}menutupnya. Polanya sama dengan{#if}:#membuka,/menutup.itemadalah nama yang kamu pilih. Di tiap putaran,itemberisi satu elemen array, berurutan dari depan.- Markup di dalam blok adalah cetakannya. Svelte menggambarnya sekali per item, jadi tiga item menghasilkan tiga
<li>.
Latihan pertama sama persis, dengan let buah = ["Apel", "Mangga", "Jeruk"]: <li> pertama berisi Apel dan yang terakhir Jeruk. Isi <li>-nya cukup {item}, tanpa baris yang diketik sendiri.
Nomor urut: index
Tambahkan nama kedua setelah koma untuk mendapat nomor putarannya:
{#each menu as item, i}
<li>{i + 1}. {item}</li>
{/each}
Hasilnya 1. Nasi Goreng, 2. Mie Ayam, 3. Es Teh. Index i dimulai dari 0, sama seperti index array di JavaScript, jadi tambahkan 1 kalau nomornya mau mulai dari 1.
Array berisi objek
Menu sungguhan punya nama, harga, dan id:
<script>
let menu = [
{ id: 1, nama: "Nasi Goreng", harga: 15000 },
{ id: 2, nama: "Mie Ayam", harga: 12000 },
{ id: 3, nama: "Es Teh", harga: 5000 },
]
</script>
<ul>
{#each menu as item, i}
<li>{i + 1}. {item.nama}: Rp {item.harga.toLocaleString("id-ID")}</li>
{/each}
</ul>
Hasilnya 1. Nasi Goreng: Rp 15.000, 2. Mie Ayam: Rp 12.000, 3. Es Teh: Rp 5.000.
item.namadanitem.hargamembaca isi objek di putaran itu.- Bisa juga dengan destructuring, membongkar objek langsung jadi variabel:
{#each menu as { nama, harga }}lalu tulis{nama}dan{harga}. idbelum dipakai di sini. Dia jadi penting di bagian key.
{:else}: kalau array-nya kosong
<ul>
{#each keranjang as item}
<li>{item}</li>
{:else}
<li>Keranjang masih kosong</li>
{/each}
</ul>
Kalau keranjang berisi [], yang tampil cuma Keranjang masih kosong. Begitu ada isinya, pesan itu hilang dan baris-barisnya muncul. Gak perlu {#if keranjang.length === 0} sendiri.
Keyed each: (item.id)
Tanpa key, Svelte mencocokkan baris dengan item berdasarkan posisi. Saat array berubah dari 3 item jadi 2, Svelte memakai ulang elemen baris pertama dan kedua, mengganti teksnya dengan item baru di posisi itu, lalu menghapus elemen baris yang paling belakang. Isi kolom <input> milik elemen, bukan milik data, jadi isinya ikut tinggal di elemen yang dipakai ulang:
Elemen <li> |
Sebelum | Sesudah, tanpa key | Sesudah, dengan key |
|---|---|---|---|
| Baris 1 | Nasi Goreng, catatan "pedas" | Mie Ayam, catatan "pedas" | (dihapus) |
| Baris 2 | Mie Ayam | Es Teh | Mie Ayam |
| Baris 3 | Es Teh | (dihapus) | Es Teh |
Tanpa key, catatan "pedas" pindah ke Mie Ayam. Itu jawaban tebakannya. Nasi Goreng memang hilang dari daftar, tapi elemen yang dihapus adalah elemen Es Teh di paling bawah.
Key memberi tahu Svelte cara mengenali tiap item:
{#each menu as item (item.id)}
<li>
{item.nama}
<input placeholder="catatan" />
</li>
{/each}
- Key ditulis dalam kurung setelah
as item. Sekarang Svelte mencocokkan baris denganid, jadi saat Nasi Goreng (id 1) hilang, elemennya yang dihapus, bersama catatannya. - Key harus unik dan tetap untuk item yang sama.
iddari database paling aman. - Dengan index, key ditulis paling akhir. Ini bentuk latihan kedua:
{#each users as user, i (user.id)}dengan<li>{i + 1}. {user.name}</li>menghasilkan1. Andidan2. Budi. - Index sebagai key,
(i), gak membantu. Setelah baris pertama dihapus, Mie Ayam jadi index 0, jadi tetap dapat elemen baris pertama.
Menambah dan menghapus item
Aturan dari pelajaran Reaktivitas tetap berlaku: di Svelte 4, daftarnya baru berubah kalau ada assignment.
menu = [...menu, { id: 4, nama: "Es Jeruk", harga: 7000 }] // tambah di belakang
menu = menu.slice(1) // buang item pertama
menu = menu.filter((m) => m.id !== 2) // buang Mie Ayam
menu.push(...) saja gak membuat baris baru muncul.
Svelte 5
{#each}, index, key, dan {:else} ditulis sama persis di Svelte 5. Bedanya cuma di state: dengan let menu = $state([...]), menu.push(...) langsung menambah baris.
⚠️ Jebakan yang sering ketemu
- Mengetik baris satu per satu.
<li>Apel</li>yang diketik sendiri gak ikut berubah saat array-nya berubah. Penguji latihan pertama menolak<li>yang langsung diikuti huruf, termasuk<li>Buah: {item}</li>. Tulis<li>{item}</li>. - Key yang gak unik.
{#each pesanan as item (item)}dengan["Es Teh", "Mie Ayam", "Es Teh"]punya dua keyEs Teh. Saat development, Svelte 4 langsung berhenti denganCannot have duplicate keys in a keyed each: Keys at index 0 and 2 with value 'Es Teh' are duplicates. Pakaiid. - Daftar yang bisa dihapus atau diurutkan ulang tanpa key. Kalau tiap baris punya isi sendiri di DOM, seperti
<input>, isinya bisa pindah ke item lain. Tambahkan(item.id). - Lupa
{/each}. Sama seperti{#if}, compiler menolak denganBlock was left open.
TL;DR: {#each array as item} ... {/each} menggambar markup di dalamnya sekali per item, berurutan. {#each array as item, i} memberi nomor putaran yang dimulai dari 0, jadi tulis {i + 1} untuk nomor dari 1. {:else} di dalam {#each} tampil saat array-nya kosong. Tanpa key, Svelte mencocokkan baris berdasarkan posisi, jadi isi <input> bisa pindah ke item lain saat baris dihapus; dengan key (item.id), tiap baris mengikuti item-nya. Key harus unik, dan index bukan key yang baik. Latihannya: {#each buah as item} dengan <li>{item}</li> menghasilkan Apel sampai Jeruk, dan {#each users as user, i (user.id)} dengan <li>{i + 1}. {user.name}</li> menghasilkan 1. Andi dan 2. Budi.