Me-render List – React
Anda mungkin ingin menampilkan beberapa komponen yang mirip dari sebuah kumpulan data. Anda dapat menggunakan method senarai (array) JavaScript untuk memanipulasi sebuah senarai data. Pada halaman ini, Anda akan menggunakan method filter() dan map() dengan React untuk menyaring dan mengubah senarai data tersebut menjadi sebuah senarai komponen.
Anda akan mempelajari
- Bagaimana me-render komponen-komponen dari sebuah senarai menggunakan method
map() - Bagaimana me-render beberapa komponen spesifik menggunakan method
filter() - Kapan dan mengapa menggunakan React keys
Me-render data dari senarai
Misalkan Anda memiliki daftar konten seperti berikut.
<ul>
<li>Creola Katherine Johnson: mathematician</li>
<li>Mario José Molina-Pasquel Henríquez: chemist</li>
<li>Mohammad Abdus Salam: physicist</li>
<li>Percy Lavon Julian: chemist</li>
<li>Subrahmanyan Chandrasekhar: astrophysicist</li>
</ul>
Semua anggota dari daftar tersebut memiliki format yang sama. Perbedaan hanya terletak pada isi konten, lebih tepatnya data mereka. Pada beberapa situasi, Anda mungkin harus menampilkan beberapa komponen yang sama dengan data yang berbeda saat membangun antarmuka, seperti daftar komentar atau galeri foto profil. Dalam situasi-situasi tersebut, Anda bisa menyimpan data tersebut ke dalam objek atau senarai JavaScript dengan menggunakan method map() dan filter() yang kemudian akan digunakan untuk me-render beberapa komponen.
Contoh untuk membuat sebuah daftar dari sebuah senarai:
- Pindahkan data ke sebuah senarai:
const people = [
'Creola Katherine Johnson: mathematician',
'Mario José Molina-Pasquel Henríquez: chemist',
'Mohammad Abdus Salam: physicist',
'Percy Lavon Julian: chemist',
'Subrahmanyan Chandrasekhar: astrophysicist'
];
- Petakan dengan menggunakan method
map()setiap anggotapeopleke sebuah senarai node JSX,listItems:
const listItems = people.map(person => <li>{person}</li>);
- Kembalikan
listItemsdari komponen Anda dengan membungkusnya terlebih dahulu dengan elemen<ul>:
return <ul>{listItems}</ul>;
Hasilnya seperti berikut:
Perhatikan bahwa sandbox di atas menampilkan pesan kesalahan:
Warning: Each child in a list should have a unique “key” prop.
Anda akan mempelajari cara memperbaiki kesalahan ini nanti. Untuk saat ini, kita akan menambahkan struktur ke data Anda.
Menyaring senarai
Kita bisa menambahkan struktur ke data ini.
const people = [{
id: 0,
name: 'Creola Katherine Johnson',
profession: 'mathematician',
}, {
id: 1,
name: 'Mario José Molina-Pasquel Henríquez',
profession: 'chemist',
}, {
id: 2,
name: 'Mohammad Abdus Salam',
profession: 'physicist',
}, {
id: 3,
name: 'Percy Lavon Julian',
profession: 'chemist',
}, {
id: 4,
name: 'Subrahmanyan Chandrasekhar',
profession: 'astrophysicist',
}];
Misalkan Anda hanya ingin menampilkan orang yang memiliki profesi 'chemist'. Anda dapat menggunakan method filter() dari JavaScript untuk mendapatkan daftar tersebut. Method ini menerima masukan berupa sebuah senarai, kemudian menguji setiap anggota dari senarai tersebut dengan sebuah fungsi uji (fungsi yang hanya mengembalikan nilai true (benar) atau false (salah)), lalu mengembalikan sebuah senarai baru yang terdiri atas anggota-anggota yang lolos uji (memperoleh nilai true).
Anda hanya menginginkan orang yang memiliki profession berupa 'chemist'. Oleh karena itu, fungsi ujinya adalah (person) => person.profession === 'chemist'. Langkahnya seperti berikut:
- Buatkan sebuah senarai baru yang terdiri atas orang-orang berprofesi
chemists, dengan memanggil methodfilter()terhadap senaraipeopledengan syaratperson.profession === 'chemist':
const chemists = people.filter(person =>
person.profession === 'chemist'
);
- Petakan setiap anggota dari senarai
chemistsmenggunakan methodmap(), yang sudah kita pelajari, menjadi sebuah senarai node JSX,listItems:
const listItems = chemists.map(person =>
<li>
<img
src={getImageUrl(person)}
alt={person.name}
/>
<p>
<b>{person.name}:</b>
{' ' + person.profession + ' '}
known for {person.accomplishment}
</p>
</li>
);
- Kembalikan
listItemsdari komponen Anda dengan membungkusnya terlebih dahulu dengan elemenul:
return <ul>{listItems}</ul>;
Hasil akhirnya seperti berikut:
import { people } from './data.js'; import { getImageUrl } from './utils.js'; export default function List() { const chemists = people.filter(person => person.profession === 'chemist' ); const listItems = chemists.map(person => <li> <img src={getImageUrl(person)} alt={person.name} /> <p> <b>{person.name}:</b> {' ' + person.profession + ' '} known for {person.accomplishment} </p> </li> ); return <ul>{listItems}</ul>; }
Sandungan
Arrow function mengembalikan, secara implisit, pernyataan tepat setelah =>, sehingga Anda tidak perlu menulis return:
const listItems = chemists.map(person =>
<li>...</li> // Return secara implisit
);
Namun, Anda harus menulis return secara eksplisit jika setelah => terdapat {!
const listItems = chemists.map(person => { // Kurung kurawal
return <li>...</li>;
});
Arrow function yang mengandung => { dianggap memiliki “badan/isi”. Anda diperbolehkan menulis fungsi yang melebihi satu baris, tetapi Anda harus menulis return. Jika Anda melupakan ini, fungsi tersebut tidak akan mengembalikan nilai apa pun!
Menjaga urutan dengan key
Perhatikan bahwa setiap sandbox di atas menampilkan pesan kesalahan di konsol:
Warning: Each child in a list should have a unique “key” prop.
Anda harus memberikan setiap anggota dari senarai sebuah key—sebuah string atau angka yang dapat mengidentifikasi setiap anggota secara unik:
<li key={person.id}>...</li>
Catatan
Setiap elemen JSX yang ada di dalam map() harus selalu memiliki key!
Key memberi tahu React mengenai hubungan antara sebuah komponen dengan sebuah anggota senarai. Hal ini krusial jika anggota senarai bisa berubah posisi (contohnya karena proses pengurutan (sorting)), ditambah, atau dihapus. Sebuah key yang baik dapat membantu React untuk mengetahui apa yang telah terjadi dan menentukan langkah optimal saat memperbarui pohon DOM.
Sebaiknya, key terkandung di dalam data Anda:
export const people = [{ id: 0, name: 'Creola Katherine Johnson', profession: 'mathematician', accomplishment: 'spaceflight calculations', imageId: 'MK3eW3A' }, { id: 1, name: 'Mario José Molina-Pasquel Henríquez', profession: 'chemist', accomplishment: 'discovery of Arctic ozone hole', imageId: 'mynHUSa' }, { id: 2, name: 'Mohammad Abdus Salam', profession: 'physicist', accomplishment: 'electromagnetism theory', imageId: 'bE7W1ji' }, { id: 3, name: 'Percy Lavon Julian', profession: 'chemist', accomplishment: 'pioneering cortisone drugs, steroids and birth control pills', imageId: 'IOjWm71' }, { id: 4, name: 'Subrahmanyan Chandrasekhar', profession: 'astrophysicist', accomplishment: 'white dwarf star mass calculations', imageId: 'lrWQx8l' }];
Pendalaman
Menampilkan beberapa node DOM untuk setiap anggota senarai
Bagaimana kalau setiap anggota senarai membutuhkan bukan hanya satu, tetapi beberapa node DOM?
Sintaksis singkat <>...</> Fragment tidak memberikan tempat untuk key, sehingga Anda harus membungkus ke dalam sebuah <div> atau menggunakan sintaksis <Fragment> yang lebih panjang:
import { Fragment } from 'react';
// ...
const listItems = people.map(person =>
<Fragment key={person.id}>
<h1>{person.name}</h1>
<p>{person.bio}</p>
</Fragment>
);
Pada akhirnya, Fragment akan hilang dari DOM dan hanya menyisakan <h1>, <p>, <h1>, <p>, dan seterusnya, pada contoh di atas.
Bagaimana Anda memperoleh key
Sumber data yang berbeda akan memberikan key yang berbeda juga, contoh:
- Data dari basis data: Jika data yang digunakan berasal dari basis data, ID dapat digunakan sebagai
keykarena sifatnya yang sudah unik. - Data lokal: Jika data dihasilkan dan disimpan secara lokal (seperti catatan pada aplikasi penulisan catatan), Anda dapat menggunakan counter yang bertambah,
crypto.randomUUID(), atau library sepertiuuid.
Aturan key
Keyharus bersifat unik antar-sibling. Namun,keyyang sama bisa digunakan lagi di senarai yang berbeda.Keytidak boleh berubah atau fungsinya akan hilang! Jangan membuatkeydi saat me-render.
Mengapa React membutuhkan key?
Bayangkan jika file yang ada di komputer Anda tidak memiliki nama. Sebagai pengganti, Anda merujuk ke file tersebut dengan urutannya—file pertama, file kedua, dan seterusnya. Saat file pertama dihapus, file kedua akan menjadi file pertama, kemudian file ketiga akan menjadi file kedua, dan seterusnya. Perujukan file menjadi tidak konsisten.
Nama file pada folder dan key pada JSX memiliki tujuan yang serupa. Mereka membantu kita mengidentifikasi anggota senarai dan membedakan mereka antar-sibling. Key yang baik tidak hanya memberikan informasi mengenai posisi item di dalam senarai, tetapi juga membantu React mengidentifikasi item tersebut sepanjang hidupnya.
Sandungan
Anda mungkin tertarik untuk menggunakan indeks pada senarai sebagai key. Sebenarnya, itulah yang digunakan React jika Anda tidak memberikan key. Namun, urutan anggota senarai dapat berubah saat ada yang ditambah, dihapus, atau diubah urutannya. Jika ini terjadi, ini bisa menimbulkan bug yang membingungkan dan sulit ditemukan.
Bukan hanya itu, sebaiknya juga tidak membuat key sembarangan, misal key={Math.random()}. Hal ini menyebabkan key baru dibuat setiap render. Akibatnya, komponen dan DOM juga ikut dibuat baru setiap render. Pada akhirnya, proses render akan menjadi lambat dan masukan dari pengguna juga akan hilang. Oleh karena itu, sebaiknya Anda menggunakan ID yang konsisten yang berasal dari data.
Perlu diperhatikan bahwa komponen tidak bisa membaca key, layaknya sebuah prop. Key hanya digunakan oleh React. Jika komponen Anda membutuhkan ID, Anda harus menggunakan prop yang berbeda, contoh <Profile key={id} userId={id} />.
Rekap
Pada halaman ini, Anda telah mempelajari:
- Bagaimana memindahkan data dari komponen ke senarai atau objek.
- Bagaimana membuat himpunan komponen yang serupa dengan menggunakan method
map(). - Bagaimana membuat senarai dari item yang memenuhi suatu kondisi menggunakan method
filter(). - Mengapa dan bagaimana menentukan
keyuntuk setiap komponen pada sebuah collection sehingga React bisa melakukan render yang optimal meskipun terdapat perubahan pada posisi atau data.
Membagi sebuah daftar menjadi dua
Pada contoh ini, terdapat sebuah daftar orang.
Anda diminta untuk menampilkan dua daftar berbeda, satu setelah yang lain: Chemists dan Bukan Chemist. Seperti sebelumnya, Anda bisa melihat apakah seseorang berprofesi sebagai chemist dengan menggunakan person.profession === 'chemist'.
import { people } from './data.js'; import { getImageUrl } from './utils.js'; export default function List() { const listItems = people.map(person => <li key={person.id}> <img src={getImageUrl(person)} alt={person.name} /> <p> <b>{person.name}:</b> {' ' + person.profession + ' '} known for {person.accomplishment} </p> </li> ); return ( <article> <h1>Scientists</h1> <ul>{listItems}</ul> </article> ); }