List Rendering Svelte — Svelte

Gunakan {#each} untuk merender list di Svelte. {#each} let buah = ["Apel", "Mangga", "Jeruk"] {#each buah as item} {item} {/each} Dengan Index {#each buah as…

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 dengan menu = 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>

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.

{: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}

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

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.

Yang akan kamu pelajari