kodingup.camp

Beranda/React Mastery: Dasar, Rendering & Hooks

Sintaks Antarmuka Deklaratif

Modul 3 dari 124 menit bacaDeclarative Interface Syntax

Isi modul

    Kenapa ini penting

    Hampir setiap baris tampilan di React ditulis dengan JSX (JavaScript XML), sintaks yang terlihat seperti HTML tapi hidup di dalam file JavaScript. JSX membuat tampilan dan logika berada berdampingan, sehingga mudah dibaca: kamu bisa melihat struktur halaman sekaligus data yang mengisinya. Tapi karena JSX sebenarnya adalah JavaScript, ada beberapa aturan yang berbeda dari HTML biasa. Pemula sering terjebak di sini: menulis class alih-alih className, mengembalikan dua elemen tanpa pembungkus, atau bingung kenapa if tidak bisa ditulis di tengah markup. Kuasai aturannya sekarang, maka sisa perjalanan React jauh lebih mulus.

    Konsep inti

    JSX bukan HTML

    Browser tidak mengerti JSX. Saat kamu menyimpan file, plugin React di Vite mengubah JSX menjadi panggilan fungsi JavaScript biasa yang menghasilkan objek elemen React. Karena itu, aturan JSX mengikuti aturan JavaScript.

    Aturan 1: Satu elemen akar (root)

    Sebuah komponen hanya boleh mengembalikan satu elemen paling luar. Alasannya sederhana: fungsi JavaScript hanya bisa me-return satu nilai. Kalau kamu butuh beberapa elemen sejajar tanpa menambah div yang tidak perlu, pakai Fragment: <>...</> (versi pendek) atau <Fragment>...</Fragment> (versi panjang, wajib jika butuh key).

    Analogi: kurir hanya mau menerima satu paket. Kalau barangmu banyak, masukkan ke satu kardus. Fragment adalah kardus transparan: membungkus tapi tidak muncul di DOM.

    Aturan 2: Semua tag harus ditutup

    Di HTML, <img> dan <br> boleh tanpa penutup. Di JSX wajib ditutup: <img />, <br />, <input />.

    Aturan 3: className dan atribut camelCase

    Karena class adalah kata kunci di JavaScript, JSX memakai className. Begitu juga for pada label menjadi htmlFor. Atribut lain yang terdiri dari beberapa kata ditulis camelCase: onclick jadi onClick, tabindex jadi tabIndex, maxlength jadi maxLength. Pengecualian: atribut aria-* dan data-* tetap ditulis dengan tanda hubung.

    HTML JSX
    class="kartu" className="kartu"
    for="email" htmlFor="email"
    onclick="..." onClick={...}
    style="color: red; font-size: 14px" style={{ color: 'red', fontSize: 14 }}
    <!-- komentar --> {/* komentar */}

    Aturan 4: Ekspresi JavaScript di dalam kurung kurawal {}

    Kurung kurawal adalah "jendela" dari markup ke JavaScript. Di dalamnya kamu boleh menulis ekspresi (sesuatu yang menghasilkan nilai): variabel, operasi a + b, pemanggilan fungsi, ternary kondisi ? a : b, array.map(...). Kamu tidak boleh menulis pernyataan seperti if, for, atau deklarasi const di dalam {}. Logika seperti itu ditulis di atas return.

    Kurung kurawal bisa dipakai di dua tempat: sebagai isi teks (<h1>{nama}</h1>) dan sebagai nilai atribut (<img src={urlFoto} />). Perhatikan: jangan diberi tanda kutip, karena src="{urlFoto}" akan dianggap teks literal.

    Aturan 5: style menerima objek

    Atribut style menerima objek JavaScript, bukan string. Itulah kenapa ada kurung kurawal ganda {{ }}: kurung luar adalah jendela JSX, kurung dalam adalah objek. Nama properti CSS juga camelCase: background-color menjadi backgroundColor. Angka tanpa satuan untuk properti seperti fontSize otomatis dianggap px.

    Aturan 6: Nilai yang tidak dirender

    true, false, null, dan undefined tidak menampilkan apa pun. Ini berguna untuk conditional rendering nanti. Tapi angka 0 tetap tampil, jebakan yang akan kita bahas di modul conditional rendering.

    Keamanan: JSX meng-escape teks

    Kalau kamu menaruh string berisi <script> di dalam {}, React menampilkannya sebagai teks biasa, bukan menjalankannya. Ini melindungi aplikasi dari serangan XSS secara default.

    Contoh kode

    // src/App.jsx, kartu profil yang memakai semua aturan JSX
    const pengguna = {
      nama: 'Dewi Lestari',
      pekerjaan: 'Frontend Developer',
      foto: 'https://i.pravatar.cc/120?img=5',
      tahunMulai: 2021,
    };
    
    function hitungPengalaman(tahunMulai) {
      return new Date().getFullYear() - tahunMulai;
    }
    
    export default function App() {
      const warnaAksen = '#0ea5e9';
      const pengalaman = hitungPengalaman(pengguna.tahunMulai);
    
      // Satu root: Fragment membungkus dua elemen sejajar
      return (
        <>
          {/* Ini komentar di dalam JSX */}
          <section className="kartu-profil" style={{ border: `2px solid ${warnaAksen}`, padding: 16 }}>
            <img src={pengguna.foto} alt={`Foto ${pengguna.nama}`} width={120} />
            <h2>{pengguna.nama}</h2>
            <p>{pengguna.pekerjaan}</p>
            <p>Pengalaman: {pengalaman} tahun</p>
            <p>Nama dalam huruf besar: {pengguna.nama.toUpperCase()}</p>
          </section>
    
          <form>
            <label htmlFor="pesan">Kirim pesan</label>
            <input id="pesan" type="text" maxLength={100} placeholder="Tulis di sini" />
          </form>
        </>
      );
    }
    // → Tampil kartu dengan border biru, foto, nama, pekerjaan,
    //   "Nama dalam huruf besar: DEWI LESTARI", dan form di bawahnya.
    

    Logika if ditulis di luar JSX, sebelum return:

    export default function Sapaan() {
      const jam = new Date().getHours();
      let salam;
      if (jam < 11) {
        salam = 'Selamat pagi';
      } else if (jam < 15) {
        salam = 'Selamat siang';
      } else if (jam < 18) {
        salam = 'Selamat sore';
      } else {
        salam = 'Selamat malam';
      }
    
      return <h1>{salam}, selamat belajar React!</h1>;
    }
    // Jam 09.00 → "Selamat pagi, selamat belajar React!"
    

    Teks berbahaya otomatis aman:

    export default function Komentar() {
      const isiDariUser = '<script>alert("hack")</script>';
      return <p>{isiDariUser}</p>;
    }
    // → Ditampilkan sebagai teks: <script>alert("hack")</script> (tidak dijalankan)
    

    Kesalahan umum

    1. Mengembalikan dua elemen sejajar tanpa pembungkus. Error "Adjacent JSX elements must be wrapped in an enclosing tag". Bungkus dengan <>...</> atau satu elemen induk.
    2. Menulis class atau for. Pakai className dan htmlFor. React memberi peringatan di console jika kamu lupa.
    3. Memberi tanda kutip pada ekspresi. src="{foto}" menghasilkan teks literal {foto}. Yang benar src={foto}.
    4. Menulis if atau for di dalam {}. Kurung kurawal hanya menerima ekspresi. Pakai ternary, &&, map, atau pindahkan logika ke atas return.
    5. Menulis style sebagai string. style="color: red" error. Pakai objek style={{ color: 'red' }}.

    Latihan

    1. Mudah, Ubah potongan HTML ini menjadi JSX yang valid: <div class="box"><label for="nama">Nama</label><input type="text" id="nama"><br></div>.
    2. Sedang, Buat komponen KartuProduk yang menampilkan nama, harga dalam format Rupiah (pakai toLocaleString('id-ID')), dan diskon 10% yang dihitung di dalam {}.
    3. Menantang, Buat komponen Jam yang menampilkan tanggal hari ini dalam format Indonesia, dan memberi warna teks merah jika hari Minggu, hitam jika bukan. Logika warna ditulis di atas return, style memakai objek.
    Lihat solusi

    1.

    export default function Form() {
      return (
        <div className="box">
          <label htmlFor="nama">Nama</label>
          <input type="text" id="nama" />
          <br />
        </div>
      );
    }
    

    2.

    export default function KartuProduk() {
      const nama = 'Kopi Gayo 250g';
      const harga = 85000;
    
      return (
        <article className="produk">
          <h3>{nama}</h3>
          <p>Harga: Rp {harga.toLocaleString('id-ID')}</p>
          <p>Setelah diskon 10%: Rp {(harga * 0.9).toLocaleString('id-ID')}</p>
        </article>
      );
    }
    // → Harga: Rp 85.000
    // → Setelah diskon 10%: Rp 76.500
    

    3.

    export default function Jam() {
      const hariIni = new Date();
      const teks = hariIni.toLocaleDateString('id-ID', {
        weekday: 'long', day: 'numeric', month: 'long', year: 'numeric',
      });
      const isMinggu = hariIni.getDay() === 0; // 0 = Minggu
      const warna = isMinggu ? 'red' : 'black';
    
      return <p style={{ color: warna, fontWeight: 'bold' }}>{teks}</p>;
    }
    // Kamis → "Kamis, 23 Oktober 2026" berwarna hitam
    

    Ringkasan

    Kuis pemahaman

    Pilih satu jawaban per soal. Penjelasan muncul setelah kamu menjawab.