kodingup.camp

Beranda/React Mastery: Dasar, Rendering & Hooks

Dasar Arsitektur Komponen

Modul 4 dari 124 menit bacaComponent Architecture Fundamentals

Isi modul

    Kenapa ini penting

    Bayangkan membangun rumah dari satu bongkahan beton raksasa. Mustahil diperbaiki: retak sedikit, semuanya harus dibongkar. Rumah dibangun dari bata, kusen, dan genteng yang terpisah; tiap bagian bisa diganti tanpa mengganggu yang lain. Komponen adalah bata di dunia React. Seluruh aplikasi React, dari tombol kecil sampai halaman penuh, tersusun dari komponen. Kemampuan memecah UI menjadi komponen yang tepat adalah pembeda antara kode React yang rapi dan kode yang sulit dirawat.

    Konsep inti

    Function component

    Komponen React modern adalah fungsi JavaScript yang mengembalikan JSX. Sudah, sesederhana itu. Dulu ada class component, tapi dokumentasi resmi react.dev sekarang mengajarkan function component + hooks, dan semua materi ini mengikuti itu.

    function Tombol() {
      return <button>Klik aku</button>;
    }
    

    Setelah didefinisikan, komponen dipakai seperti tag HTML: <Tombol />.

    Nama wajib PascalCase

    Nama komponen harus diawali huruf kapital, misalnya Navbar, KartuProduk, DaftarTugas. Ini bukan sekadar gaya: React membedakan tag huruf kecil (<div>, <button>) sebagai elemen HTML bawaan, dan tag huruf besar sebagai komponen buatanmu. Kalau kamu menulis <navbar />, React mengira itu tag HTML bernama navbar yang tidak ada, sehingga komponenmu tidak pernah dipanggil.

    Komponen harus murni (pure) saat render

    Komponen sebaiknya bertindak seperti fungsi matematika: input sama, output sama. Jangan mengubah variabel di luar komponen atau memanggil API saat render. Efek samping punya tempat sendiri (event handler dan useEffect, dibahas nanti). Inilah kenapa StrictMode merender dua kali: supaya ketidakmurnian cepat terlihat.

    Jangan mendefinisikan komponen di dalam komponen lain

    Tulis setiap komponen di level teratas file (top-level). Komponen yang didefinisikan di dalam komponen lain akan dibuat ulang di setiap render, sehingga state di dalamnya ter-reset dan performa menurun.

    Cara memecah UI menjadi komponen

    Langkah praktis yang disarankan dokumentasi React ("Thinking in React"):

    1. Gambar atau lihat desain UI.
    2. Beri kotak di setiap bagian yang punya tanggung jawab sendiri.
    3. Satu komponen idealnya mengerjakan satu hal. Kalau ia membesar, pecah lagi.
    4. Susun jadi hierarki: komponen induk berisi komponen anak.

    Contoh halaman toko kopi:

    App
    ├── Header
    │   ├── Logo
    │   └── Navigasi
    ├── DaftarProduk
    │   └── KartuProduk (diulang untuk setiap produk)
    └── Footer
    

    Tanda sebuah bagian layak menjadi komponen: dipakai berulang (kartu produk), cukup besar untuk punya nama sendiri (header), atau punya logika sendiri (form login).

    Export dan import

    Satu file biasanya berisi satu komponen utama. Ada dua jenis export:

    Jenis Cara export Cara import Aturan
    Default export default function Header() {} import Header from './Header.jsx' Satu per file; nama saat import bebas
    Named export function Logo() {} import { Logo } from './Logo.jsx' Boleh banyak per file; nama harus sama persis

    Konvensi umum: satu file satu komponen dengan default export, dan nama file sama dengan nama komponen (Header.jsx berisi Header). Ekstensi .jsx dipakai untuk file yang berisi JSX.

    Struktur folder sederhana yang rapi:

    src/
    ├── App.jsx
    ├── main.jsx
    └── components/
        ├── Header.jsx
        ├── Footer.jsx
        └── KartuProduk.jsx
    

    Contoh kode

    Pecah halaman toko kopi menjadi beberapa file:

    // src/components/Header.jsx
    export function Logo() {
      return <strong className="logo">☕ Kopi Nusantara</strong>;
    }
    
    export default function Header() {
      return (
        <header className="header">
          <Logo />
          <nav>
            <a href="#menu">Menu</a> | <a href="#kontak">Kontak</a>
          </nav>
        </header>
      );
    }
    
    // src/components/KartuProduk.jsx
    export default function KartuProduk() {
      return (
        <article className="kartu">
          <h3>Kopi Toraja</h3>
          <p>Rp 90.000</p>
          <button>Tambah</button>
        </article>
      );
    }
    
    // src/components/Footer.jsx
    export default function Footer() {
      const tahun = new Date().getFullYear();
      return <footer>© {tahun} Kopi Nusantara</footer>;
    }
    
    // src/App.jsx, merakit semua komponen
    import Header from './components/Header.jsx';
    import KartuProduk from './components/KartuProduk.jsx';
    import Footer from './components/Footer.jsx';
    
    export default function App() {
      return (
        <>
          <Header />
          <main id="menu">
            <h2>Menu Hari Ini</h2>
            {/* Komponen yang sama bisa dipakai berulang */}
            <KartuProduk />
            <KartuProduk />
            <KartuProduk />
          </main>
          <Footer />
        </>
      );
    }
    // → Header dengan logo, tiga kartu "Kopi Toraja", lalu footer "© 2026 Kopi Nusantara"
    

    Ketiga kartu masih identik. Di modul berikutnya kita akan memberi data berbeda ke tiap kartu lewat props.

    Contoh yang salah dan benar soal komponen bersarang:

    // ❌ SALAH: Tombol didefinisikan di dalam Halaman
    export default function Halaman() {
      function Tombol() {
        return <button>OK</button>;
      }
      return <Tombol />; // Tombol dibuat ulang setiap Halaman render
    }
    
    // ✅ BENAR: definisikan di top-level
    function Tombol() {
      return <button>OK</button>;
    }
    
    export function HalamanBenar() {
      return <Tombol />;
    }
    

    Kesalahan umum

    1. Nama komponen huruf kecil. function kartu() lalu <kartu /> tidak akan jalan sebagai komponen. Pakai Kartu.
    2. Lupa return. Fungsi dengan kurung kurawal tanpa return menghasilkan undefined, layar kosong. Pastikan ada return (...).
    3. Salah pasangan import/export. Mengimpor named export tanpa kurung kurawal (import Logo from ... padahal export function Logo) menghasilkan error atau undefined. Cocokkan jenisnya.
    4. Komponen raksasa. Satu file 500 baris berisi header, list, form, dan modal sekaligus. Pecah berdasarkan tanggung jawab.
    5. Mendefinisikan komponen di dalam komponen lain. Pindahkan ke top-level agar state tidak ter-reset.

    Latihan

    1. Mudah, Buat komponen Salam yang menampilkan "Halo, peserta bootcamp!" lalu pakai tiga kali di App.
    2. Sedang, Pecah halaman blog sederhana menjadi komponen Navbar, Artikel, dan Sidebar di folder components/, lalu rakit di App.jsx.
    3. Menantang, Buat file components/Ikon.jsx yang berisi tiga named export (IkonRumah, IkonCari, IkonUser, masing-masing mengembalikan emoji dalam span) dan satu default export BarIkon yang memakai ketiganya. Impor keduanya di App.
    Lihat solusi

    1.

    function Salam() {
      return <p>Halo, peserta bootcamp!</p>;
    }
    
    export default function App() {
      return (
        <>
          <Salam />
          <Salam />
          <Salam />
        </>
      );
    }
    

    2.

    // src/components/Navbar.jsx
    export default function Navbar() {
      return <nav>Beranda · Tentang · Kontak</nav>;
    }
    
    // src/components/Artikel.jsx
    export default function Artikel() {
      return (
        <article>
          <h2>Belajar React dari Nol</h2>
          <p>React adalah library untuk membangun UI...</p>
        </article>
      );
    }
    
    // src/components/Sidebar.jsx
    export default function Sidebar() {
      return <aside>Artikel populer: JSX, Props, State</aside>;
    }
    
    // src/App.jsx
    import Navbar from './components/Navbar.jsx';
    import Artikel from './components/Artikel.jsx';
    import Sidebar from './components/Sidebar.jsx';
    
    export default function App() {
      return (
        <>
          <Navbar />
          <div className="layout">
            <Artikel />
            <Sidebar />
          </div>
        </>
      );
    }
    

    3.

    // src/components/Ikon.jsx
    export function IkonRumah() {
      return <span aria-label="rumah">🏠</span>;
    }
    export function IkonCari() {
      return <span aria-label="cari">🔍</span>;
    }
    export function IkonUser() {
      return <span aria-label="user">👤</span>;
    }
    
    export default function BarIkon() {
      return (
        <div className="bar-ikon">
          <IkonRumah /> <IkonCari /> <IkonUser />
        </div>
      );
    }
    
    // src/App.jsx
    import BarIkon, { IkonCari } from './components/Ikon.jsx';
    
    export default function App() {
      return (
        <>
          <BarIkon />
          <p>Cari sesuatu? <IkonCari /></p>
        </>
      );
    }
    

    Ringkasan

    Kuis pemahaman

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