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.

You will learn

  • 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:

  1. 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'
];
  1. Petakan dengan menggunakan method map() setiap anggota people ke sebuah senarai node JSX, listItems:
const listItems = people.map(person => <li>{person}</li>);
  1. Kembalikan listItems dari komponen Anda dengan membungkusnya terlebih dahulu dengan elemen <ul>:
return <ul>{listItems}</ul>;

Hasilnya seperti berikut:

const people = [
  'Creola Katherine Johnson: mathematician',
  'Mario José Molina-Pasquel Henríquez: chemist',
  'Mohammad Abdus Salam: physicist',
  'Percy Lavon Julian: chemist',
  'Subrahmanyan Chandrasekhar: astrophysicist'
];

export default function List() {
  const listItems = people.map(person =>
    <li>{person}</li>
  );
  return <ul>{listItems}</ul>;
}

Perhatikan bahwa sandbox di atas menampilkan pesan kesalahan:

Console
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',
}, {
name: 'Percy Lavon Julian',
profession: 'chemist',
}, {
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:

  1. Buatkan sebuah senarai baru yang terdiri atas orang-orang berprofesi chemists, dengan memanggil method filter() terhadap senarai people dengan syarat person.profession === 'chemist':
const chemists = people.filter(person =>
person.profession === 'chemist'
);
  1. Petakan setiap anggota dari senarai chemists menggunakan method map(), 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>
);
  1. Kembalikan listItems dari komponen Anda dengan membungkusnya terlebih dahulu dengan elemen ul:
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>;
}

Pitfall

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:

Console
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>

Note

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, // Digunakan sebagai key pada JSX
  name: 'Creola Katherine Johnson',
  profession: 'mathematician',
  accomplishment: 'spaceflight calculations',
  imageId: 'MK3eW3A'
}, {
  id: 1, // Digunakan sebagai key pada JSX
  name: 'Mario José Molina-Pasquel Henríquez',
  profession: 'chemist',
  accomplishment: 'discovery of Arctic ozone hole',
  imageId: 'mynHUSa'
}, {
  id: 2, // Digunakan sebagai key pada JSX
  name: 'Mohammad Abdus Salam',
  profession: 'physicist',
  accomplishment: 'electromagnetism theory',
  imageId: 'bE7W1ji'
}, {
  id: 3, // Digunakan sebagai key pada JSX
  name: 'Percy Lavon Julian',
  profession: 'chemist',
  accomplishment: 'pioneering cortisone drugs, steroids and birth control pills',
  imageId: 'IOjWm71'
}, {
  id: 4, // Digunakan sebagai key pada JSX
  name: 'Subrahmanyan Chandrasekhar',
  profession: 'astrophysicist',
  accomplishment: 'white dwarf star mass calculations',
  imageId: 'lrWQx8l'
}];

Deep Dive

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 key karena 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 seperti uuid.

Aturan key

  • Key harus bersifat unik antar-sibling. Namun, key yang sama bisa digunakan lagi di senarai yang berbeda.
  • Key tidak boleh berubah atau fungsinya akan hilang! Jangan membuat key di 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.

Pitfall

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} />.

Recap

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 key untuk setiap komponen pada sebuah collection sehingga React bisa melakukan render yang optimal meskipun terdapat perubahan pada posisi atau data.

Challenge 1 of 4:
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>
  );
}