Conditional Rendering

Komponen anda sering diperlukan untuk menampilkan hal yang berbeda tergantung dari beberapa kondisi yang berbeda. Di React, anda dapat melakukan render JSX secara bersyarat menggunakan sintaks JavaScript seperti pernyataan if, &&, dan ? : operator.

You will learn

  • Cara mengembalikan JSX yang berbeda tergantung dari suatu kondisi
  • Bagaimana cara memasukkan atau mengecualikan sepotong JSX secara bersyarat
  • Pintasan sintaks bersyarat umum yang akan anda temukan di basis kode React

Mengembalikan JSX secara Bersyarat

Katakanlah anda memiliki komponen PackingList yang melakukan render pada beberapa Items, yang dapat ditandai secara dikemas atau tidak:

function Item({ name, isPacked }) {
  return <li className="item">{name}</li>;
}

export default function PackingList() {
  return (
    <section>
      <h1>Andrian Ride's Packing List</h1>
      <ul>
        <Item 
          isPacked={true} 
          name="Space suit" 
        />
        <Item 
          isPacked={true} 
          name="Helmet with a golden leaf" 
        />
        <Item 
          isPacked={false} 
          name="Photo of Tam" 
        />
      </ul>
    </section>
  );
}

Perhatikan bahwa beberapa komponen Item memiliki properti isPacked yang disetel menjadi true daripada false. Anda ingin menambahkan tanda centang (✔) ke Item yang dikemas jika isPacked={true}.

Anda dapat menulis ini sebagai pernyataan if/else seperti ini:

if (isPacked) {
return <li className="item">{name}</li>;
}
return <li className="item">{name}</li>;

Jika properti isPacked adalah true, kode ini mengembalikan JSX tree yang berbeda. Dengan perubahan ini, beberapa item mendapat tanda centang di bagian akhir:

function Item({ name, isPacked }) {
  if (isPacked) {
    return <li className="item">{name}</li>;
  }
  return <li className="item">{name}</li>;
}

export default function PackingList() {
  return (
    <section>
      <h1>Andrian Ride's Packing List</h1>
      <ul>
        <Item 
          isPacked={true} 
          name="Space suit" 
        />
        <Item 
          isPacked={true} 
          name="Helmet with a golden leaf" 
        />
        <Item 
          isPacked={false} 
          name="Photo of Tam" 
        />
      </ul>
    </section>
  );
}

Coba melakukan edit apa yang dikembalikan dalam kedua kasus tersebut, dan lihat bagaimana hasilnya berubah!

Perhatikan bagaimana anda membuat logika bercabang dengan pernyataan if dan return menggunakan JavaScript. Di React, alur kontrol (seperti kondisi) ditangani oleh JavaScript.

Tidak mengembalikan Apa Pun secara Bersyarat dengan null

Dalam kondisi tertentu, anda tidak ingin me-render apa pun. Sebagai Contoh, katakan anda tidak mau menampilkan item yang dikemas. Sebuah komponen harus mengembalikan sesuatu. Dalam kasus ini, anda dapat mengambalikan null:

if (isPacked) {
return null;
}
return <li className="item">{name}</li>;

Jika isPacked adalah true, komponen tidak akan mengembalikan apa pun, null. Jika tidak, itu akan mengembalikan JSX untuk di-render.

function Item({ name, isPacked }) {
  if (isPacked) {
    return null;
  }
  return <li className="item">{name}</li>;
}

export default function PackingList() {
  return (
    <section>
      <h1>Andrian Ride's Packing List</h1>
      <ul>
        <Item 
          isPacked={true} 
          name="Space suit" 
        />
        <Item 
          isPacked={true} 
          name="Helmet with a golden leaf" 
        />
        <Item 
          isPacked={false} 
          name="Photo of Tam" 
        />
      </ul>
    </section>
  );
}

Dalam praktiknya, mengembalikan null dari sebuah komponen itu tidak umum karena dapat mengejutkan developer yang mencoba untuk me-render-nya. Lebih sering, anda akan menyertakan atau mengecualikan komponen secara bersyarat di komponen induk JSX. Berikut adalah cara untuk melakukannya!

Secara Bersyarat memasukkan JSX

Pada contoh sebelumnya, anda mengontrol JSX tree mana (if any!) yang akan dikembalikan oleh komponen. Anda mungkin telah memperhatikan beberapa duplikasi dalam hasil render:

<li className="item">{name}</li>

mirip dengan

<li className="item">{name}</li>

Kedua branches bersyarat tersebut mengembalikan <li className="item">...</li>:

if (isPacked) {
return <li className="item">{name}</li>;
}
return <li className="item">{name}</li>;

Meskipun duplikasi ini tidak berbahaya, ini dapat membuka kode anda lebih susah untuk di-maintain. Bagaimana jika anda ingi mengganti classNamenya? Anda harus melakukannya di dua tempat dalam kode anda! Dalam situasi seperti itu, anda dapat menyertakan sedikit JSX secara bersyarat untuk membuat kode anda lebih DRY.

Operator (? :) Bersyarat (ternary)

JavaScript memiliki syntax yang ringkas untuk menulis ekspresi bersyarat — operator bersyarat atau sering disebut sebagai “ternary operator”.

Daripada ini:

if (isPacked) {
return <li className="item">{name}</li>;
}
return <li className="item">{name}</li>;

Anda dapat menulis ini:

return (
<li className="item">
{isPacked ? name + ' ✔' : name}
</li>
);

anda dapat membacanya sebagai “jika isPacked adalah true, maka (?) render name + ' ✔', jika tidak (:) render name.

Deep Dive

Apakah kedua contoh tersebut sepenuhnya sama?

Jika anda berasal dari latar belakang pemrograman berorientasi objek, anda mungkin berasumsi bahwa kedua contoh tersebut sedikit berbeda karena salah satunya dapat membuat dua jenis “instansi” <li> berbeda. Tetapi elemen JSX bukan “instansi” karena mereka tidak memiliki state internal dan bukan node DOM yang sebenarnya. Itu deskripsi ringan, seperti cetak biru. Jadi kedua contoh ini, sebenarnya, adalah benar-benar sama. Preserving and Resetting State menjelaskan lebih detil bagaimana hal ini bekerja.

Sekarang katakanlah anda ingin membungkus teks item yang sudah selesai ke dalam tag HTML lain, seperti <del> untuk mencoretnya. Anda bahkan dapat menambahkan lebih banyak baris baru dan tanda kurung sehingga lebih mudah untuk menyarankan lebih banyak JSX di setiap kasus:

function Item({ name, isPacked }) {
  return (
    <li className="item">
      {isPacked ? (
        <del>
          {name + ' ✔'}
        </del>
      ) : (
        name
      )}
    </li>
  );
}

export default function PackingList() {
  return (
    <section>
      <h1>Andrian Ride's Packing List</h1>
      <ul>
        <Item 
          isPacked={true} 
          name="Space suit" 
        />
        <Item 
          isPacked={true} 
          name="Helmet with a golden leaf" 
        />
        <Item 
          isPacked={false} 
          name="Photo of Tam" 
        />
      </ul>
    </section>
  );
}

Gaya ini bekerja dengan baik untuk kondisi yang sederhana, tetapi gunakan dengan secukupnya. Jika komponen anda berantakan dengan terlalu banyak markup bersyarat bersarang (nested conditional markup), pertimbangkan untuk mengekstrak komponen turunan untuk membersihkan semuanya. Di React, markup adalah bagian dari kode anda, sehingga anda dapat menggunakan alat seperti variabel (variables) dan fungsi (functions) untuk merapikan ekspresi yang kompleks.

Operator Logis AND (&&)

Pintasan umum lainnya yang akan anda temui adalah JavaScript logical AND (&&) operator. Di Dalam komponen React, hal tersebut sering muncul ketika anda ingin me-render beberapa JSX apabila memiliki kondisi true, atau tidak me-render sebaliknya. Dengan &&, anda dapat me-render tanda centang secara bersyarat hanya jika isPacked adalah true:

return (
<li className="item">
{name} {isPacked && '✔'}
</li>
);

Anda dapat membaca ini sebagai “jika isPacked, maka (&&) render tanda centang, jika tidak, tidak render apa pun”.

Seperti berikut:

function Item({ name, isPacked }) {
  return (
    <li className="item">
      {name} {isPacked && '✔'}
    </li>
  );
}

export default function PackingList() {
  return (
    <section>
      <h1>Andrian Ride's Packing List</h1>
      <ul>
        <Item 
          isPacked={true} 
          name="Space suit" 
        />
        <Item 
          isPacked={true} 
          name="Helmet with a golden leaf" 
        />
        <Item 
          isPacked={false} 
          name="Photo of Tam" 
        />
      </ul>
    </section>
  );
}

Ekspresi && JavaScript mengembalikan nilai sisi kanannya (dalam kasus ini, tanda centang) jika sisi kirinya (kondisi kita) adalah true. Tetapi jika kondisinya adalah false, seluruh ekspresi menjadi false. React menganggap false sebagai sebuah “lubang” pada JSX tree, sama seperti null atau undefined, dan tidak me-render apa pun di tempatnya.

Pitfall

Jangan menaruh Angka di sisi kiri &&.

Untuk menguji kondisi tersebut, JavaScript mengubah sisi kiri menjadi sebuah boolean secara otomatis. Namun, jika sisi kiri adalah 0, maka seluruh ekspresi akan mendapatkan nilai (0) tesebut, dan React akan dengan senang hati me-render 0 daripada tidak sama sekali.

Sebagai contoh, kesalahan umum yang sering terjadi adalah menulis kode seperti messageCount && <p>Pesan Baru</p>. Sangat mudah untuk berasumsi bahwa itu tidak me-render/menghasilkan apa-apa ketika messageCount adalah 0, tapi itu benar-benar me-render 0 itu sendiri!

Untuk memperbaikinya, jadikan sisi kiri sebagai boolean: messageCount > 0 && <p>Pesan Baru</p>.

Menugaskan JSX secara Bersyarat ke sebuah Variabel

Saat pintasan menghalangi dalam penulisan kode biasa, coba gunakan pernyataan if dan sebuah variabel. Anda dapat menetapkan ulang variabel yang telah ditentukan dengan menggunakan let, jadi mulailah dengan menyediakan konten default yang ingin anda tampilkan, namanya:

let itemContent = name;

Gunakan pernyataan if untuk menetapkan kembali ekspresi JSX ke itemContent jika isPacked adalah true:

if (isPacked) {
itemContent = name + " ✔";
}

Kurung kurawal membuka “jendela ke JavaScript”. Menyematkan variabel dengan kurung kurawal di JSX tree yang dikembalikan, menyarangkan ekspresi yang sebelumnya dihitung di dalam JSX:

<li className="item">
{itemContent}
</li>

Gaya ini paling bertele-tele, tetapi juga yang paling fleksibel. Berikut adalah caranya:

function Item({ name, isPacked }) {
  let itemContent = name;
  if (isPacked) {
    itemContent = name + " ✔";
  }
  return (
    <li className="item">
      {itemContent}
    </li>
  );
}

export default function PackingList() {
  return (
    <section>
      <h1>Andrian Ride's Packing List</h1>
      <ul>
        <Item 
          isPacked={true} 
          name="Space suit" 
        />
        <Item 
          isPacked={true} 
          name="Helmet with a golden leaf" 
        />
        <Item 
          isPacked={false} 
          name="Photo of Tam" 
        />
      </ul>
    </section>
  );
}

Seperti sebelumnya, cara ini bekerja tidak hanya pada teks, tetapi juga pada JSX yang sewenang-wenang:

function Item({ name, isPacked }) {
  let itemContent = name;
  if (isPacked) {
    itemContent = (
      <del>
        {name + " ✔"}
      </del>
    );
  }
  return (
    <li className="item">
      {itemContent}
    </li>
  );
}

export default function PackingList() {
  return (
    <section>
      <h1>Sally Ride's Packing List</h1>
      <ul>
        <Item 
          isPacked={true} 
          name="Space suit" 
        />
        <Item 
          isPacked={true} 
          name="Helmet with a golden leaf" 
        />
        <Item 
          isPacked={false} 
          name="Photo of Tam" 
        />
      </ul>
    </section>
  );
}

Jika anda tidak terbiasa dengan JavaScript, variasi dari gaya ini mungkin tampak berlebihan pada awalnya. Namun, mempelajarinya akan membantu anda dalam membaca dan menulis kode JavaScript apa pun — dan bukan hanya komponen React! Pilih salah satu yang anda sukai sebagai permulaan, dan lihat kembali referensi ini jika anda lupa cara kerja yang lain.

Recap

  • Di React, anda mengontrol logika percabangan dengan JavaScript.
  • Anda dapat mengembalikan ekspresi JSX secara bersyarat menggunakan pernyataan if.
  • Anda dapat menyimpan beberapa JSX ke dalam sebuah variabel secara bersyarat dan kemudian memasukkannya ke dalam JSX yang lain dengan menggunakan kurung kurawal.
  • Di JSX, {cond ? <A /> : <B />} berarti “jika cond, render <A />, jika tidak <B />.
  • Di JSX, {cond && <A />} berarti “jika cond, render <A />, jika tidak render apa pun”.
  • Pintasan itu umum, tapi anda tidak harus menggunakannya jika anda lebih menyukai pernyataan if.

Challenge 1 of 3:
Tampilkan ikon untuk item yang tidak lengkap dengan menggunakan ? :

Gunakan operator bersyarat (cond ? a : b) untuk me-render sebuah ❌ jika isPacked bukan true.

function Item({ name, isPacked }) {
  return (
    <li className="item">
      {name} {isPacked && '✔'}
    </li>
  );
}

export default function PackingList() {
  return (
    <section>
      <h1>Andrian Ride's Packing List</h1>
      <ul>
        <Item 
          isPacked={true} 
          name="Space suit" 
        />
        <Item 
          isPacked={true} 
          name="Helmet with a golden leaf" 
        />
        <Item 
          isPacked={false} 
          name="Photo of Tam" 
        />
      </ul>
    </section>
  );
}