Komponen Anda akan seringkali perlu menampilkan hal yang berbeda tergantung pada kondisi yang berbeda. Di React, Anda dapat me-render JSX secara kondisional menggunakan sintaksis JavaScript seperti pernyataan if, &&, dan operator ? :.

Anda akan mempelajari

  • Cara mengembalikan JSX yang berbeda tergantung pada suatu kondisi
  • Cara menyertakan atau mengecualikan bagian dari JSX secara kondisional
  • Pintasan (shortcut) sintaksis kondisional yang umum yang akan Anda temui di basis kode (codebase) React

Mengembalikan JSX secara kondisional

Katakanlah Anda memiliki komponen PackingList yang me-render beberapa Item, yang dapat ditandai sebagai dikemas atau tidak:

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

export default function PackingList() {
  return (
    <section>
      <h1>Daftar Pengemasan Sally Ride</h1>
      <ul>
        <Item 
          isPacked={true} 
          name="Pakaian luar angkasa" 
        />
        <Item 
          isPacked={true} 
          name="Helm berwarna emas" 
        />
        <Item 
          isPacked={false} 
          name="Foto Tam" 
        />
      </ul>
    </section>
  );
}

Perhatikan bahwa beberapa komponen Item memiliki prop isPacked yang disetel ke true, bukan false. Anda ingin menambahkan tanda centang (✔) pada item yang sudah dikemas jika isPacked={true}.

Anda dapat menuliskannya sebagai pernyataan if/else seperti ini:

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

Jika prop isPacked bernilai true, kode ini mengembalikan pohon JSX yang berbeda. Dengan perubahan ini, beberapa item akan mendapatkan 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>Daftar Pengemasan Sally Ride</h1>
      <ul>
        <Item 
          isPacked={true} 
          name="Pakaian luar angkasa" 
        />
        <Item 
          isPacked={true} 
          name="Helm berwarna emas" 
        />
        <Item 
          isPacked={false} 
          name="Foto Tam" 
        />
      </ul>
    </section>
  );
}

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

Perhatikan bagaimana Anda membuat logika bercabang dengan pernyataan if dan return JavaScript. Dalam React, aliran kontrol (seperti kondisi) ditangani oleh JavaScript.

Tidak mengembalikan elemen apa pun secara kondisional dengan null

Dalam beberapa situasi, Anda tidak ingin me-render apa pun. Sebagai contoh, katakanlah Anda tidak ingin menampilkan item yang dikemas sama sekali. Sebuah komponen harus mengembalikan sesuatu. Dalam kasus ini, Anda dapat mengembalikan null:

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

Jika nilai isPacked adalah true, komponen tidak akan mengembalikan apa-apa, null. Jika tidak, komponen ini 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>Daftar Pengemasan Sally Ride</h1>
      <ul>
        <Item 
          isPacked={true} 
          name="Pakaian luar angkasa" 
        />
        <Item 
          isPacked={true} 
          name="Helm berwarna emas" 
        />
        <Item 
          isPacked={false} 
          name="Foto Tam" 
        />
      </ul>
    </section>
  );
}

Dalam praktiknya, mengembalikan null dari sebuah komponen tidaklah umum karena dapat mengejutkan pengembang yang mencoba me-render-nya. Lebih sering, Anda akan menyertakan atau mengecualikan komponen secara kondisional dalam JSX komponen induk. Inilah cara untuk melakukannya!

Menyertakan JSX secara kondisional

Pada contoh sebelumnya, Anda mengontrol pohon JSX mana (jika ada!) yang akan dikembalikan oleh komponen. Anda mungkin telah melihat beberapa duplikasi pada keluaran render:

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

is very similar to

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

Kedua cabang kondisional mengembalikan <li className="item">...</li>:

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

Meskipun duplikasi ini tidak berbahaya, namun dapat membuat kode Anda menjadi lebih sulit untuk dipelihara. Bagaimana jika Anda ingin mengubah className? Anda harus melakukannya di dua tempat dalam kode Anda! Dalam situasi seperti ini, Anda dapat menyertakan sedikit JSX secara kondisional untuk membuat kode Anda lebih [DRY.] (https://en.wikipedia.org/wiki/Don%27t_repeat_yourself)

Operator kondisional (ternary) (? :)

JavaScript memiliki sintaks yang ringkas untuk menulis ekspresi bersyarat — the operator kondisional atau “operator ternary”.

Daripada ini:

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

Anda bisa menulis ini:

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

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

Pendalaman

Apakah kedua contoh ini sepenuhnya setara?

Jika Anda berasal dari latar belakang pemrograman berorientasi objek, Anda mungkin berasumsi bahwa kedua contoh di atas sangat berbeda karena salah satu contoh tersebut dapat membuat dua “instance” yang berbeda dari <li>. Tetapi elemen JSX bukanlah “instance” karena mereka tidak memiliki state internal dan bukan merupakan simpul DOM yang sebenarnya. Mereka adalah deskripsi ringan, seperti cetak biru. Jadi, kedua contoh ini, pada kenyataannya, sebenarnya sepenuhnya setara. Mempertahankan dan Mengatur Ulang State menjelaskan secara detail tentang cara kerjanya.

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

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

export default function PackingList() {
  return (
    <section>
      <h1>Daftar Pengemasan Sally Ride</h1>
      <ul>
        <Item 
          isPacked={true} 
          name="Pakaian luar angkasa" 
        />
        <Item 
          isPacked={true} 
          name="Helm berwarna emas" 
        />
        <Item 
          isPacked={false} 
          name="Foto Tam" 
        />
      </ul>
    </section>
  );
}

Model seperti ini bekerja dengan baik untuk kondisi sederhana, tetapi gunakan secukupnya. Jika komponen Anda menjadi berantakan dengan terlalu banyak markup kondisional bersarang, pertimbangkan untuk mengekstrak komponen turunan untuk membereskannya. Di React, markup adalah bagian dari kode Anda, sehingga Anda dapat menggunakan alat bantu seperti variabel dan fungsi untuk merapikan ekspresi yang kompleks.

Operator logis AND (&&)

Pintasan umum lainnya yang akan Anda temui adalah operator logis AND (&&) JavaScript. Di dalam komponen React, hal ini sering muncul ketika Anda ingin me-render beberapa JSX ketika kondisinya true, atau tidak me-render apapuin jika sebaliknya. Dengan &&, Anda dapat me-render tanda centang secara kondisional hanya jika isPacked bernilai true:

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

Anda dapat membacanya sebagai “jika isPacked, maka (&&) render tanda centang, sebaliknya, jangan render apa pun”.

Here it is in action:

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

export default function PackingList() {
  return (
    <section>
      <h1>Daftar Pengemasan Sally Ride</h1>
      <ul>
        <Item 
          isPacked={true} 
          name="Pakaian luar angkasa" 
        />
        <Item 
          isPacked={true} 
          name="Helm berwarna emas" 
        />
        <Item 
          isPacked={false} 
          name="Foto Tam" 
        />
      </ul>
    </section>
  );
}

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

Sandungan

Jangan menaruh angka di sisi kiri &&.

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

Sebagai contoh, kesalahan yang sering terjadi adalah menulis kode seperti messageCount && <p>Pesan baru</p>. Sangat mudah untuk mengasumsikan bahwa kode tersebut tidak melakukan apa-apa ketika messageCount bernilai 0, namun sebenarnya kode tersebut benar-benar me-render 0 itu sendiri!

Untuk memperbaikinya, buatlah sisi kiri menjadi boolean: messageCount > 0 && <p>Pesan baru</p>.

Menetapkan JSX secara kondisional ke sebuah variabel

Ketika pintasan menghalangi penulisan kode biasa, cobalah menggunakan pernyataan if dan variabel. Anda dapat menetapkan ulang variabel yang didefinisikan dengan let, jadi mulailah dengan memberikan konten default yang ingin Anda tampilkan, yaitu nama:

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 dalam JavaScript”. Tempelkan variabel dengan kurung kurawal pada pohon JSX yang dikembalikan, menyarangkan ekspresi yang telah dikalkulasi sebelumnya di dalam JSX:

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

Model ini adalah model yang paling bertele-tele, tetapi juga paling fleksibel. Ini contohnya:

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

export default function PackingList() {
  return (
    <section>
      <h1>Daftar Pengemasan Sally Ride</h1>
      <ul>
        <Item 
          isPacked={true} 
          name="Pakaian luar angkasa" 
        />
        <Item 
          isPacked={true} 
          name="Helm berwarna emas" 
        />
        <Item 
          isPacked={false} 
          name="Foto Tam" 
        />
      </ul>
    </section>
  );
}

Seperti sebelumnya, ini tidak hanya berfungsi untuk teks, tetapi juga untuk JSX sembarang:

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>Daftar Pengemasan Sally Ride</h1>
      <ul>
        <Item 
          isPacked={true} 
          name="Pakaian luar angkasa" 
        />
        <Item 
          isPacked={true} 
          name="Helm berwarna emas" 
        />
        <Item 
          isPacked={false} 
          name="Foto Tam" 
        />
      </ul>
    </section>
  );
}

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

Rekap

  • Di React, Anda dapat mengontrol logika percabangan dengan JavaScript.
  • Anda dapat mengembalikan ekspresi JSX secara kondisional dengan pernyataan if.
  • Anda dapat menyimpan beberapa JSX secara kondisional ke sebuah variabel dan kemudian menyertakannya di dalam JSX lain dengan menggunakan kurung kurawal.
  • Dalam JSX, {cond ? <A /> : <B />} berarti “jika cond, render <A />, sebaliknya <B />.
  • Dalam JSX, {cond && <A />} berarti “jika cond, render <A />, sebaliknya jangan render apa pun”.
  • Pintasan ini umum digunakan, tetapi Anda tidak perlu menggunakannya jika Anda lebih suka if biasa.

Tantangan 1 dari 3:
Menampilkan ikon untuk item yang tidak lengkap dengan ? :

Gunakan operator kondisional (cond ? a : b) untuk me-render ❌ jika isPacked tidak true.

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

export default function PackingList() {
  return (
    <section>
      <h1>Daftar Pengemasan Sally Ride</h1>
      <ul>
        <Item 
          isPacked={true} 
          name="Pakaian luar angkasa" 
        />
        <Item 
          isPacked={true} 
          name="Helm berwarna emas" 
        />
        <Item 
          isPacked={false} 
          name="Foto Tam" 
        />
      </ul>
    </section>
  );
}