Apa yang Dikeluhkan Error Ini
Ketika kamu mengembangkan aplikasi React, suatu saat kamu hampir pasti akan menjumpai pesan error berikut di console browser:
Warning: Each child in a list should have a unique "key" prop.
Check the render method of `ComponentName`. See https://reactjs.org/docs/lists-and-keys.html for more information.Pesan ini muncul sebagai warning, bukan error fatal—aplikasi tetap berjalan, tapi React secara eksplisit memberi tahu bahwa ada sesuatu yang salah dalam cara kamu merender daftar elemen. Artinya dalam bahasa sehari-hari: setiap elemen anak yang di-render melalui loop atau pemetaan array wajib memiliki properti key yang unik. Tanpa key yang unik, React tidak bisa membedakan satu elemen dari elemen lainnya dalam daftar, sehingga proses reconciling (pembaruan DOM virtual) menjadi tidak efisien dan berpotensi menghasilkan bug visual yang sulit dilacak.
Asal masalahnya Secara teknis, ketika kamu menggunakan Array.prototype.map() atau loop sejenis untuk merender kumpulan komponen, React membutuhkan identitas stabil untuk tiap item. Jika key tidak disertakan, React secara default akan menggunakan index posisi array sebagai key—dan ini yang berbahaya karena index bersifat dinamis. Saat item ditambah, dihapus, atau di-reorder, index berubah, dan React bisa salah menganggap sebuah elemen sebagai elemen lain. Inilah mengapa React memancarkan warning ini: bukan sekadar formalitas, melainkan indikator nyata bahwa rendering-mu berisiko mengalami inconsistency.
Perhatikan contoh kode berikut yang memicu warning ini:
function UserList({ users }) {
return (
<ul>
{users.map((user) => (
<li>{user.name}</li>
))}
</ul>
);
}Pada potongan di atas, tidak ada prop key yang diberikan ke setiap <li>, sehingga React tidak punya cara untuk mengidentifikasi masing-masing item secara unik.
Akar Masalahnya
Ada beberapa root cause yang paling sering menjadi sumber warning ini. Diurutkan dari yang paling umum:
| Penyebab | Contoh yang salah | Perbaikan |
|---|---|---|
| Memakai index array | key={index} |
Pakai ID stabil: key={item.id} |
| Key duplikat | key={item.name} saat nama kembar |
Gabungkan: key={`${item.id}-${i}`} |
| Key hilang di Fragment | <>{items.map(...)} tanpa key |
Pakai <React.Fragment key={...}> |
Pertama, tidak memberikan prop key sama sekali saat memetakan array ke JSX. Ini adalah penyebab paling klasik dan paling sering ditemui, terutama di kalangan developer yang baru mengenal React. Developer menulis .map() dan langsung return JSX tanpa menyadari bahwa React mengharuskan atribut key pada elemen terluar yang di-return dari map.
Kedua, menggunakan index array sebagai key. Secara teknis ini tidak memicu warning—karena key memang ada—tapi ini adalah anti-pattern yang setara dampak buruknya dengan tidak memberi key sama sekali. Developer sering menulis key={index} karena merupakan cara paling mudah, namun saat list bersifat dinamis (item bisa dihapus, ditambah, atau di-sort), index yang berubah membuat React kehilangan track identitas item sebenarnya.
Ketiga, menggunakan nilai yang tidak unik sebagai key, misalnya field yang duplikat antar item. Contoh umum: menggunakan key={item.category} di mana beberapa item berbagi category yang sama. React akan memunculkan warning lain (Encountered two children with the same key), dan ini menyebabkan React memperlakukan item-item dengan key sama sebagai item yang sama, sehingga hanya merender satu di antaranya.
Keempat, fragment wrapper tanpa key. Ketika return dari map adalah <>...</> (React.Fragment shorthand), prop key tidak bisa diletakkan di sana. Developer lupa mengganti ke <React.Fragment key={...}>, sehingga warning tetap muncul meskipun mereka sudah "menambahkan" key di dalam fragment.
Kelima, nested mapping di mana key hanya diberikan di level outer loop tapi tidak di inner loop. Developer yang melakukan double .map() kadang hanya memberi key pada loop pertama dan lupa bahwa loop kedua juga memproduksi list yang membutuhkan key.
Untuk memastikan penyebab mana yang kamu alami, lakukan pemeriksaan berikut:
- Cek apakah ada
.map()di kode komponen yang bermasalah. Jika ada dan tidak adakeydi elemen return-nya, itu penyebab pertama. - Jika
keysudah ada tapi berupa index (key={i}ataukey={index}), itu penyebab kedua. - Jika
keymenggunakan field data tapi warning berubah jadi "two children with the same key", cek apakah field tersebut benar-benar unik di seluruh item. Jika tidak, itu penyebab ketiga. - Jika return map menggunakan
<>...</>dan key tidak bisa ditempel, itu penyebab keempat. - Jika ada
.map()di dalam.map(), periksa kedua level—kemungkinan besar itu penyebab kelima.
Langkah Perbaikan
Langkah 1: Identifikasi lokasi yang memicu warning
Buka developer tools browser (F12), pergi ke tab Console, dan cari warning tersebut. React menyertakan nama komponen dan metode render yang bermasalah. Perhatikan output berikut:
Warning: Each child in a list should have a unique "key" prop.
Check the render method of `TodoList`.Dari sini kamu tahu bahwa masalah ada di komponen TodoList. Buka file komponen tersebut.
Langkah 2: Cari pemanggilan .map() di komponen tersebut
Cari semua instance .map( di dalam JSX return komponen. Setiap .map() yang merender elemen React wajib diberi key.
Langkah 3: Tambahkan prop key menggunakan identifier unik dari data
Jika item memiliki id dari database, itu adalah kandidat terbaik untuk key:
function TodoList({ todos }) {
return (
<ul>
{todos.map((todo) => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
);
}Hasil yang muncul: warning di console menghilang sepenuhnya setelah hot-reload.
Langkah 4: Jika tidak ada id unik, gunakan kombinasi field yang unik
Kadang data belum punya field id. Kamu bisa mengkombinasikan dua atau lebih field yang secara bersama-sama membentuk identitas unik:
function ScheduleList({ schedules }) {
return (
<div>
{schedules.map((s) => (
<ScheduleCard key={`${s.day}-${s.timeSlot}`}>{s.title}</ScheduleCard>
))}
</div>
);
}Langkah 5: Untuk Fragment shorthand, ganti ke bentuk eksplisit
Jika kamu menggunakan <>...</> sebagai wrapper di dalam map, ganti ke <React.Fragment>:
// ❌ Salah — key tidak bisa diletakkan di shorthand fragment
{items.map((item) => (
<><span>{item.label}</span><span>{item.value}</span></>
))}
// ✅ Benar — gunakan Fragment eksplisit
{items.map((item) => (
<React.Fragment key={item.id}>
<span>{item.label}</span>
<span>{item.value}</span>
</React.Fragment>
))}Langkah 6: Untuk nested mapping, beri key unik di setiap level
{categories.map((cat) => (
<div key={cat.id}>
{cat.items.map((item) => (
<ItemCard key={item.id}>{item.name}</ItemCard>
))}
</div>
))}Verifikasi solusi berhasil
Setelah melakukan perbaikan, verifikasi dengan cara berikut:
- Refresh halaman dan buka Console—pastikan warning sudah hilang.
- Lakukan interaksi yang memodifikasi list (tambah, hapus, re-order item) dan pastikan UI ter-update dengan benar tanpa ada elemen yang "tertukar" atau tidak ter-render.
- Jika menggunakan React DevTools, periksa tab Profiler—re-render harus hanya terjadi pada item yang berubah, bukan seluruh list.
Perbaikan Permanen
Memberikan key secara manual setiap kali menulis .map() adalah langkah korektif, tapi bagaimana memastikan error ini tidak kembali muncul di masa depan? Berikut konfigurasi dan Cara yang disarankan yang membentengi codebase kamu:
Konfigurasi ESLint Rule
Pasang rule ESLint react/jsx-key yang secara otomatis mendeteksi penggunaan .map() tanpa key:
npm install --save-dev eslint eslint-plugin-reactTambahkan konfigurasi berikut di .eslintrc.json:
{
"plugins": ["react"],
"rules": {
"react/jsx-key": "error"
}
}Dengan konfigurasi ini, ESLint akan menampilkan error (bukan warning) setiap kali ada iterasi array yang merender JSX tanpa key. Ini mencegah kode bermasalah masuk ke codebase sekalipun developer lupa. Integrasi ke CI/CD pipeline memastikan bahwa PR yang melanggar rule ini gagal di-build, menjadikan proteksi ini permanen.
Kebiasaan yang baik: Desain Data dengan ID Sejak Awal
Pastikan setiap entity yang akan di-render sebagai list sudah memiliki field identifier unik sejak level data model. Jika data berasal dari API backend, koordinasikan dengan tim backend agar setiap response list menyertakan field id. Jika data dibuat di frontend (misalnya form entries yang belum disimpan), generate ID menggunakan library seperti uuid atau crypto.randomUUID():
import { v4 as uuidv4 } from 'uuid';
const newTodo = {
id: uuidv4(),
title: inputTitle,
completed: false,
};Jadi, setiap item selalu punya ID stabil sejak penciptaannya, dan kamu tidak pernah tergoda menggunakan index sebagai key.
Praktik terbaik: Hindari Index Sebagai Key Secara Total
Ada satu pengecualian di mana index sebagai key acceptable: ketika list bersifat static, read-only, dan tidak pernah di-reorder atau difilter. Namun sebagai aturan praktis, lebih baik menganggap index sebagai key itu selalu salah. Mentalitas ini mengeliminasi edge case dan membuat kode lebih robust terhadap perubahan future requirement.
Perbedaan Antar OS
Tidak ada perbedaan perilaku error ini antara Windows, macOS, atau Linux. Warning ini dihasilkan oleh React runtime di browser, yang berperilaku identik lintas platform. Namun, untuk setup ESLint, pastikan versi Node.js yang digunakan konsisten di seluruh OS tim development agar rule react/jsx-key berjalan seragam. Di Windows, path konfigurasi ESLint terkadang perlu penanganan khusus jika menggunakan backslash—gunakan eslint-use-flat-config atau format path secara normalisasi.
Kalau Masih Belum Berhasil
Kalau solusi di atas tidak work
Jika kamu sudah menambahkan key tapi warning masih muncul, kemungkinan besar ada lebih dari satu titik yang bermasalah. React hanya mencetak satu warning per komponen, jadi memperbaiki satu titik tidak menghilangkan warning dari titik lain di komponen yang sama atau komponen berbeda. Lakukan pencarian menyeluruh:
grep -rn "\.map(" src/ --include="*.jsx" --include="*.tsx"Periksa setiap hasil untuk memastikan key ada. Juga periksa penggunaan .forEach() yang diikuti push ke array, lalu array di-render—pattern ini juga membutuhkan key tapi sering terlewat karena tidak langsung menggunakan .map().
Kasus sulit lainnya: komponen anak yang menerima children berupa list. Jika parent me-render <Parent>{items.map(...)}</Parent>, maka key harus diletakkan di elemen return map, bukan di <Parent>. Developer kadang salah menaruh key di wrapper parent padahal yang di-iterate adalah children-nya.
Cara baca log
K etika warning ini muncul di console browser, React menyertakan informasi yang sangat berguna untuk melacak sumber masalah. Perhatikan struktur log berikut:
Warning: Each child in a list should have a unique "key" prop.
Check the render method of `TodoList`. See https://reactjs.org/link/warning-keys for more information.
in TodoItem (at TodoList.jsx:12)
in TodoList (at App.jsx:8)
in App (at src/index.js:7)Dari log di atas, kita bisa membaca beberapa hal penting:
Nama komponen —
TodoListadalah komponen yang melakukan rendering list tanpakey. Langsung periksa methodrenderatau return statement komponen tersebut.Stack trace — Baris
(06995 di bawahnya menunjukkan rantai komponen dari anak ke ancestor. Fokus pada **baris paling atas** (TodoItem at TodoList.jsx:12) karena itulah lokasi tepat di manaKey` hilang.Nomor baris — Jika source map aktif, React menampilkan line number. Gunakan itu untuk langsung melompat ke file dan baris yang bermasalah.
Tip: Di development mode, React hanya mencetak warning sekali per komponen untuk menghindari spam console. Jadi, jika kamu memperbaiki satu instance dan warning hilang, itu belum tentu berarti semua instance sudah benar. Refresh halaman dan perhatikan apakah warning muncul lagi dari komponen lain.
Untuk kasus diD)/di0ECMA Script"!D6/"9@4189 di mana stack trace tidak menunjukkan baris (misalnya pada setup Next.js atau Vite dengan sourcemap bermasalah), aktifkan breakpoint di React DevTools. caranya: buka tab Components → pilih komponen yang dicurigai → lihat panel kanan untuk props yang berupa array. Cek apakah setiap elemen array memiliki key saat di-render.
Catatan Penutup
Warning "each child in a list should have a unique key prop" adalah salah satu issue paling umum di React, sekaligus salah satu yang paling mudah diperbaiki. Intinya: setiap kali kamu melakukan map atau iterasi untuk me-render elemen, pastikan setiap elemen punya prop key yang unik dan stabil. Hindari menggunakan index array sebagai key kecuali list kamu benar-benar statis. Dengan memahami mengapa React membutuhkan key—untuk reconcilation yang efisien—kamu tidak hanya memperbaiki warning, tapi juga mencegah bug UI yang sulit debug di kemudian hari.