Keys & Reconciliation — React

Pas user hapus item dari shopping cart, React harus tahu MANA item yang dihapus — biar cuma 1 row yang di-remove dari DOM, bukan rebuild seluruh list. Pas…

Tiap kali datanya berubah, React menggambar ulang komponenmu, lalu membandingkan hasil yang baru dengan yang lama supaya tahu bagian halaman mana yang perlu diubah. Proses membandingkan ini namanya reconciliation, dan di sebuah list, React memasangkan item lama dengan item baru lewat key. Bayangin guru yang mencatat muridnya berdasarkan nomor kursi: "kursi 1 suka bola". Begitu ada murid baru duduk di kursi 1 dan yang lain geser satu kursi, catatan itu sekarang menempel ke murid baru. Kalau catatannya ditulis berdasarkan NIS (nomor induk siswa), catatan selalu ikut muridnya. key={index} itu nomor kursi, key={s.id} itu NIS.

🧪 Tebakan cepat: list Andi, Budi, Citra pakai key={index}, dan tiap baris punya kotak <input>. Kamu mengetik "suka bola" di baris Andi, lalu Dewi ditambahkan di paling atas. Sekarang "suka bola" ada di baris siapa? Tebak dulu, jawabannya ada di bagian "Bug key={index}: catatan pindah baris".

Render ulang dan reconciliation

Aturan yang dipakai React waktu membandingkan:

  1. Tipe elemen beda, misalnya <div> jadi <span>: elemen lama dibuang beserta isinya, lalu dibuat yang baru.
  2. Tipe elemen sama: elemennya dipakai ulang, cuma atribut dan teks yang berubah yang diperbarui.
  3. Di list, item lama dan baru dipasangkan lewat key. Key yang sama dipakai ulang, key baru dibuatkan elemen baru, key yang hilang elemennya dibuang.

Elemen yang dipakai ulang membawa semua yang ada di dalamnya: teks yang sudah diketik di <input>, posisi kursor, fokus. Di situlah key jadi penting.

Bug key={index}: catatan pindah baris

function DaftarSiswa({ siswa }) {
  return (
    <ul>
      {siswa.map((s, index) => (
        <li key={index}>
          {s.nama} <input placeholder="catatan" />
        </li>
      ))}
    </ul>
  );
}

<input> ini gak diatur oleh React: teks yang kamu ketik disimpan oleh elemen <input> itu sendiri di DOM. Ketik "suka bola" di baris Andi, lalu tambahkan Dewi di paling atas. siswa berubah dari Andi, Budi, Citra jadi Dewi, Andi, Budi, Citra.

key Sebelum Sesudah <input> yang dipakai
0 Andi, berisi "suka bola" Dewi input lama key 0: "suka bola"
1 Budi Andi input lama key 1: kosong
2 Citra Budi input lama key 2: kosong
3 belum ada Citra input baru: kosong

React melihat key 0 masih ada, jadi <li> dan <input> milik key 0 dipakai ulang. Teks namanya diperbarui jadi Dewi, tapi isi kotak input-nya gak disentuh. Hasilnya, "suka bola" muncul di baris Dewi, dan catatan Andi hilang. Itu jawaban tebakannya. Gak ada error, gak ada peringatan: tampilannya salah diam-diam.

Hal yang sama terjadi waktu list diurutkan ulang, difilter, atau ada item yang dihapus dari tengah: nomor urutnya bergeser, isinya pindah ke orang lain.

Pakai id yang stabil

Cukup ganti satu baris:

<li key={s.id}>
  {s.nama} <input placeholder="catatan" />
</li>

Datanya { id: 1, nama: "Andi" }, { id: 2, nama: "Budi" }, { id: 3, nama: "Citra" }, lalu Dewi dengan id: 4.

key Sebelum Sesudah <input> yang dipakai
4 belum ada Dewi input baru: kosong
1 Andi, berisi "suka bola" Andi input lama key 1: "suka bola"
2 Budi Budi input lama key 2
3 Citra Citra input lama key 3

Key 4 belum pernah ada, jadi cuma Dewi yang dibuatkan elemen baru, disisipkan di atas. Andi, Budi, dan Citra dikenali lewat id-nya, elemennya tetap, dan "suka bola" tetap di baris Andi. Cuma 1 elemen baru yang dibuat, dan gak ada isi yang salah tempat.

Aturan memilih key

💡 Ganti key untuk mulai dari nol

key juga bisa dipasang di komponen di luar list. Kalau key sebuah komponen berubah, React menganggapnya komponen lain: yang lama dibuang, yang baru dibuat dari nol, termasuk semua isinya.

<FormCatatan key={siswaDipilih.id} siswa={siswaDipilih} />

Pindah dari Andi ke Budi, key berubah dari 1 jadi 2, jadi form dibuat ulang dan kotak isiannya kosong lagi. Tanpa key, form lama dipakai ulang, dan catatan untuk Andi masih tertulis waktu Budi yang dipilih.

⚠️ Jebakan yang sering ketemu

TL;DR: Tiap data berubah, React render ulang lalu membandingkan deskripsi UI baru (Virtual DOM) dengan yang lama. Proses ini namanya reconciliation, atau diffing, dan hasilnya cuma bagian yang beda yang diubah di DOM. Di list, item dipasangkan lewat key: key sama berarti elemen lama dipakai ulang beserta isinya. key={index} bikin isi input pindah ke baris lain begitu ada item disisipkan di atas, dihapus, atau diurutkan ulang. Pakai key={item.id}: unik di list itu dan stabil. Jangan Math.random(). Mengganti key sebuah komponen membuatnya mulai dari nol.

Yang akan kamu pelajari