Bab 1: Komponen Pertamamu
⏱ 3 menit bacaApa Itu Component?
Kamu pasti pernah main puzzle. Setiap keping puzzle punya bentuk unik, tapi kalau digabung jadi gambar utuh. Component di React itu keping puzzle — setiap component punya tampilan dan fungsi sendiri, tapi kalau dirakit jadi website utuh.
Secara teknis, component adalah fungsi JavaScript yang mengembalikan markup (JSX). Itu aja. Sesimpel itu.
function Tombol() {
return <button>Klik Saya</button>;
}Coba sendiri: Edit kode di bawah dan lihat hasilnya langsung!
Boom — itu udah component. Namanya Tombol, tugasnya menampilkan satu tombol.
Kenapa Pakai Component?
Tanpa Component (HTML biasa):
<!-- Navbar di halaman 1 -->
<nav><a href="/">Home</a><a href="/about">About</a></nav>
<!-- Navbar di halaman 2 (copy-paste) -->
<nav><a href="/">Home</a><a href="/about">About</a></nav>
<!-- Navbar di halaman 3 (copy-paste lagi) -->
<nav><a href="/">Home</a><a href="/about">About</a></nav>Mau ubah satu link? Harus edit di semua halaman. 😱
Dengan Component:
function Navbar() {
return <nav><a href="/">Home</a><a href="/about">About</a></nav>;
}
// Pakai di mana aja:
<Navbar />
<Navbar />
<Navbar />Mau ubah? Edit sekali di component, otomatis berubah di semua tempat. ✨
Cara Membuat Component
Langkah 1: Buat Fungsi
function Profil() {
// ...
}Langkah 2: Return JSX
function Profil() {
return (
<img
src="https://example.com/foto.jpg"
alt="Foto profil"
/>
);
}Langkah 3: Export
export default function Profil() {
return (
<img
src="https://example.com/foto.jpg"
alt="Foto profil"
/>
);
}export default artinya: "Ini component utama di file ini, bisa di-import file lain."
Aturan Penamaan Component
WAJIB: Huruf Kapital di Awal
// ✅ BENAR
function KartuProduk() { ... }
function NavbarUtama() { ... }
function TombolBeli() { ... }
// ❌ SALAH — React anggap ini HTML tag
function kartuProduk() { ... }
function navbar() { ... }Kenapa?
React membedakan component vs HTML tag berdasarkan huruf pertama:
<div>→ huruf kecil → HTML tag<Navbar>→ huruf besar → Component buatan kamu
Kalau kamu tulis <navbar>, React cari tag HTML bernama "navbar" — yang nggak ada. Error.
Konvensi Penamaan
- PascalCase untuk component:
KartuProduk,DaftarKontak,FormLogin - camelCase untuk variabel/fungsi biasa:
handleKlik,jumlahItem,isLoading
Menyusun Component (Nesting)
Component bisa dipanggil di dalam component lain. Ini namanya composition — kekuatan utama React.
function Avatar() {
return <img src="foto.jpg" alt="avatar" style={{ borderRadius: "50%" }} />;
}
function KartuUser() {
return (
<div style={{ border: "1px solid #ccc", padding: "16px" }}>
<Avatar />
<h2>Yazid Akbar</h2>
<p>Web Developer</p>
</div>
);
}
function App() {
return (
<div>
<h1>Tim Kami</h1>
<KartuUser />
<KartuUser />
<KartuUser />
</div>
);
}Hierarki Component
App (parent)
└── KartuUser (child dari App)
└── Avatar (child dari KartuUser)
App= parent dariKartuUserKartuUser= child dariApp, parent dariAvatarAvatar= child dariKartuUser
Boneka besar berisi boneka lebih kecil, yang berisi boneka lebih kecil lagi. Setiap boneka "lengkap" sendiri, tapi bisa ditaruh di dalam boneka lain.
Satu File vs Banyak File
Satu File (untuk component kecil yang terkait):
// components/Galeri.jsx
function Foto({ src, alt }) {
return <img src={src} alt={alt} style={{ width: "200px" }} />;
}
export default function Galeri() {
return (
<div>
<Foto src="1.jpg" alt="Foto 1" />
<Foto src="2.jpg" alt="Foto 2" />
<Foto src="3.jpg" alt="Foto 3" />
</div>
);
}Foto nggak di-export karena cuma dipakai di file ini. Galeri di-export karena dipakai file lain.
Banyak File (untuk component yang di-reuse di banyak tempat):
src/
├── components/
│ ├── Navbar.jsx
│ ├── Footer.jsx
│ ├── Tombol.jsx
│ └── KartuProduk.jsx
├── App.jsx
└── main.jsx
Kapan pisah file?
- Component dipakai di lebih dari 1 tempat → pisah
- Component sudah lebih dari 50 baris → pertimbangkan pisah
- Component punya logika kompleks sendiri → pisah
⚠️ Jebakan
1. Definisi Component di Dalam Component
// ❌ SALAH — JANGAN definisikan component di dalam component lain!
function Galeri() {
function Foto() { // Ini akan dibuat ulang setiap render!
return <img src="foto.jpg" />;
}
return <Foto />;
}
// ✅ BENAR — definisikan di level teratas
function Foto() {
return <img src="foto.jpg" />;
}
function Galeri() {
return <Foto />;
}Kenapa salah? Kalau Foto didefinisikan di dalam Galeri, setiap kali Galeri re-render, React bikin Foto baru dari nol. Ini bikin:
- Performa lambat
- State di
Fotohilang setiap render - Bug yang susah dilacak
2. Lupa Return
// ❌ Nggak return apa-apa — component kosong
function Judul() {
<h1>Halo</h1>; // Lupa return!
}
// ✅ Benar
function Judul() {
return <h1>Halo</h1>;
}3. Return Multi-line Tanpa Kurung
// ❌ Error — JavaScript anggap return selesai di baris itu
function Kartu() {
return
<div>
<h1>Judul</h1>
</div>;
}
// ✅ Benar — bungkus dengan kurung ()
function Kartu() {
return (
<div>
<h1>Judul</h1>
</div>
);
}Ini karena JavaScript punya fitur "Automatic Semicolon Insertion" — dia otomatis taruh ; setelah return kalau baris berikutnya kosong.
Contoh Penggunaan Nyata
Component Navbar
function NavLink({ href, children }) {
return (
<a href={href} style={{ marginRight: "16px", textDecoration: "none" }}>
{children}
</a>
);
}
function Navbar() {
return (
<nav style={{ background: "#333", padding: "12px" }}>
<NavLink href="/">Home</NavLink>
<NavLink href="/produk">Produk</NavLink>
<NavLink href="/tentang">Tentang</NavLink>
<NavLink href="/kontak">Kontak</NavLink>
</nav>
);
}Component Card Testimonial
function Bintang({ jumlah }) {
return <span>{"⭐".repeat(jumlah)}</span>;
}
function Testimonial({ nama, teks, rating }) {
return (
<div style={{ border: "1px solid #eee", padding: "16px", borderRadius: "8px", marginBottom: "12px" }}>
<Bintang jumlah={rating} />
<p style={{ fontStyle: "italic" }}>"{teks}"</p>
<p style={{ fontWeight: "bold" }}>— {nama}</p>
</div>
);
}
function HalamanTestimonial() {
return (
<div>
<h2>Apa Kata Mereka</h2>
<Testimonial nama="Budi" teks="Produknya bagus banget!" rating={5} />
<Testimonial nama="Ani" teks="Pengiriman cepat, recommended!" rating={4} />
<Testimonial nama="Citra" teks="Harga terjangkau, kualitas oke." rating={4} />
</div>
);
}🏋️ Challenge
Challenge 1: Galeri Foto
Buat component Galeri yang menampilkan 4 foto ilmuwan. Buat component Foto terpisah yang menerima props nama dan src.
💡 Hint
function Foto({ nama, src }) {
return (
<figure>
<img src={src} alt={nama} />
<figcaption>{nama}</figcaption>
</figure>
);
}✅ Solusi
function Foto({ nama, src }) {
return (
<figure style={{ display: "inline-block", margin: "10px", textAlign: "center" }}>
<img src={src} alt={nama} style={{ width: "150px", height: "150px", borderRadius: "8px" }} />
<figcaption>{nama}</figcaption>
</figure>
);
}
export default function Galeri() {
return (
<div>
<h1>Ilmuwan Hebat</h1>
<Foto nama="Albert Einstein" src="https://upload.wikimedia.org/wikipedia/commons/thumb/3/3e/Einstein_1921.jpg/200px-Einstein_1921.jpg" />
<Foto nama="Marie Curie" src="https://upload.wikimedia.org/wikipedia/commons/thumb/7/7e/Marie_Curie_c1920.jpg/200px-Marie_Curie_c1920.jpg" />
<Foto nama="Nikola Tesla" src="https://upload.wikimedia.org/wikipedia/commons/thumb/d/d4/N.Tesla.JPG/200px-N.Tesla.JPG" />
<Foto nama="Isaac Newton" src="https://upload.wikimedia.org/wikipedia/commons/thumb/3/3b/Portrait_of_Sir_Isaac_Newton%2C_1689.jpg/200px-Portrait_of_Sir_Isaac_Newton%2C_1689.jpg" />
</div>
);
}Challenge 2: Component Bersarang 3 Level
Buat hierarki:
App
└── Halaman
└── Artikel
└── Penulis
Setiap component menampilkan sesuatu + memanggil child-nya.
✅ Solusi
function Penulis({ nama }) {
return <p style={{ color: "#666", fontStyle: "italic" }}>Ditulis oleh: {nama}</p>;
}
function Artikel({ judul, isi, penulis }) {
return (
<article style={{ marginBottom: "24px", padding: "16px", border: "1px solid #ddd", borderRadius: "8px" }}>
<h2>{judul}</h2>
<p>{isi}</p>
<Penulis nama={penulis} />
</article>
);
}
function Halaman() {
return (
<main style={{ maxWidth: "600px", margin: "0 auto" }}>
<h1>Blog Saya</h1>
<Artikel
judul="Belajar React Itu Mudah"
isi="React adalah library JavaScript untuk membangun UI. Dengan component, kode jadi rapi dan reusable."
penulis="Yazid"
/>
<Artikel
judul="Tips Produktif Coding"
isi="Gunakan Pomodoro technique: 25 menit fokus, 5 menit istirahat. Ulangi 4 kali, lalu istirahat panjang."
penulis="Budi"
/>
</main>
);
}
export default function App() {
return <Halaman />;
}Sudah paham materi ini?
Tandai sebagai selesai untuk melacak progress-mu.