Setelah menyiapkan project React di artikel sebelumnya, saatnya memahami konsep paling fundamental React: komponen dan props. Komponen adalah blok bangunan UI — bayangkan seperti Lego, di mana setiap bagian interface (tombol, kartu, navigasi) adalah komponen yang bisa digunakan berulang kali. Props adalah cara meneruskan data ke komponen, seperti parameter fungsi.
Function Component Dasar
Di React modern, komponen adalah fungsi JavaScript yang mengembalikan JSX:
// Komponen sederhana — nama harus dimulai huruf kapital!
function Salam() {
return <h1>Selamat datang di KamusNgoding! 👋</h1>;
}
// Penggunaan di App.jsx
function App() {
return (
<div>
<Salam />
<Salam /> {/* Bisa digunakan berkali-kali */}
</div>
);
}
Aturan penting: Nama komponen harus dimulai huruf kapital.
<salam />akan dianggap HTML tag, bukan komponen React.<Salam />adalah komponen React.
Props — Meneruskan Data ke Komponen
// Komponen dengan props
function KartuPengguna(props) {
return (
<div style={{ border: "1px solid #ccc", padding: "16px", borderRadius: "8px" }}>
<h3>{props.nama}</h3>
<p>Email: {props.email}</p>
<p>Jabatan: {props.jabatan}</p>
</div>
);
}
// Penggunaan — kirim data melalui atribut JSX
function App() {
return (
<div>
<KartuPengguna
nama="Ali Akbar"
email="ali@email.com"
jabatan="Frontend Developer"
/>
<KartuPengguna
nama="Budi Santoso"
email="budi@email.com"
jabatan="Backend Developer"
/>
</div>
);
}
Destructuring Props — Cara yang Lebih Bersih
// Destructuring langsung di parameter fungsi
function KartuProduk({ nama, harga, stok, kategori }) {
return (
<div className="kartu-produk">
<h3>{nama}</h3>
<p>Kategori: {kategori}</p>
<p>Harga: Rp {harga.toLocaleString("id-ID")}</p>
<p>Stok: {stok} unit</p>
</div>
);
}
// Penggunaan
<KartuProduk
nama="Laptop ThinkPad"
harga={15000000}
stok={5}
kategori="Elektronik"
/>
Props children — Konten di Dalam Komponen
// children adalah konten yang ditulis di antara tag buka dan tutup
function Kartu({ judul, children }) {
return (
<div style={{ border: "1px solid var(--color-border)", padding: "20px" }}>
<h2 style={{ color: "var(--color-primary)" }}>{judul}</h2>
<div>{children}</div>
</div>
);
}
// Penggunaan
function App() {
return (
<Kartu judul="Informasi Akun">
<p>Username: ali_akbar</p>
<p>Level: Premium</p>
<button>Edit Profil</button>
</Kartu>
);
}
Default Props
function Badge({ teks, warna = "#00FF88", ukuran = "small" }) {
const style = {
backgroundColor: warna,
padding: ukuran === "small" ? "4px 8px" : "8px 16px",
borderRadius: "4px",
fontSize: ukuran === "small" ? "12px" : "16px",
};
return <span style={style}>{teks}</span>;
}
// Penggunaan
<Badge teks="Pemula" /> {/* Menggunakan default */}
<Badge teks="Mahir" warna="#FF6B6B" ukuran="large" />
Conditional Rendering
Menggunakan && (Render jika true)
function StatusPengguna({ isLogin, nama }) {
return (
<div>
{isLogin && <p>Halo, {nama}! Kamu sudah login.</p>}
{!isLogin && <p>Silakan login untuk melanjutkan.</p>}
</div>
);
}
Menggunakan Ternary ? :
function TombolStok({ tersedia }) {
return (
<button
disabled={!tersedia}
style={{ backgroundColor: tersedia ? "#00FF88" : "#8B949E" }}
>
{tersedia ? "Tambah ke Keranjang" : "Stok Habis"}
</button>
);
}
Menggunakan if dalam JSX (untuk kondisi kompleks)
function StatusPesanan({ status }) {
let konten;
let warna;
if (status === "menunggu") {
konten = "⏳ Menunggu konfirmasi";
warna = "#F0E05A";
} else if (status === "dikirim") {
konten = "🚚 Sedang dikirim";
warna = "#818CF8";
} else if (status === "selesai") {
konten = "✅ Pesanan selesai";
warna = "#00FF88";
} else {
konten = "❌ Pesanan dibatalkan";
warna = "#FF6B6B";
}
return (
<span style={{ color: warna, fontWeight: "bold" }}>
{konten}
</span>
);
}
Rendering List dengan map()
function DaftarProduk({ produk }) {
return (
<ul>
{produk.map((item) => (
// key WAJIB ada! Gunakan ID unik, bukan indeks array jika bisa
<li key={item.id}>
<strong>{item.nama}</strong> — Rp {item.harga.toLocaleString("id-ID")}
</li>
))}
</ul>
);
}
// Penggunaan
const daftar_produk = [
{ id: 1, nama: "Laptop", harga: 15000000 },
{ id: 2, nama: "Mouse", harga: 250000 },
{ id: 3, nama: "Keyboard", harga: 750000 },
];
<DaftarProduk produk={daftar_produk} />
Mengapa
keypenting? React menggunakankeyuntuk melacak elemen mana yang berubah saat list diperbarui. Tanpa key yang unik, React mungkin salah mengidentifikasi elemen dan menyebabkan bug yang susah dilacak.
Memecah Komponen — Component Composition
// Setiap komponen punya satu tanggung jawab
function Avatar({ src, nama }) {
return (
<img
src={src}
alt={nama}
style={{ width: 40, height: 40, borderRadius: "50%" }}
/>
);
}
function InfoPengguna({ nama, peran }) {
return (
<div>
<strong>{nama}</strong>
<small style={{ color: "var(--color-text-muted)", display: "block" }}>
{peran}
</small>
</div>
);
}
// Komponen yang lebih besar menggunakan komponen lebih kecil
function HeaderPengguna({ pengguna }) {
return (
<div style={{ display: "flex", alignItems: "center", gap: "12px" }}>
<Avatar src={pengguna.avatarUrl} nama={pengguna.nama} />
<InfoPengguna nama={pengguna.nama} peran={pengguna.peran} />
</div>
);
}
// Penggunaan
const pengguna = {
nama: "Ali Akbar",
peran: "Frontend Developer",
avatarUrl: "/images/ali.jpg"
};
<HeaderPengguna pengguna={pengguna} />
Pertanyaan yang Sering Diajukan
Mengapa harus ada satu root element di JSX?
JSX dikompilasi menjadi React.createElement() yang hanya bisa mengembalikan satu nilai. Jika ingin mengembalikan beberapa elemen tanpa wrapper div, gunakan Fragment: <>...</> atau <React.Fragment>...</React.Fragment>. Fragment tidak menghasilkan elemen DOM tambahan.
Apakah props bisa berupa fungsi?
Ya! Props bisa berisi nilai apapun yang valid di JavaScript: string, number, boolean, array, objek, bahkan fungsi. Meneruskan fungsi sebagai props adalah cara utama untuk komunikasi dari child ke parent component — ini yang disebut “callback props” dan akan dipelajari lebih dalam di artikel event handling.
Mengapa menggunakan index array sebagai key tidak disarankan?
Jika kamu menggunakan indeks array sebagai key dan urutan list berubah (karena insert, delete, atau sort), React akan memiliki referensi key yang tidak akurat. Ini bisa menyebabkan bug subtle seperti form yang tidak direset atau animasi yang salah. Gunakan ID unik dari data jika tersedia.
Berapa banyak komponen yang ideal dalam satu file?
Tidak ada aturan ketat, tapi konvensi umum: satu komponen besar per file, tapi komponen kecil terkait boleh di file yang sama. Jika komponen mulai terasa terlalu besar (lebih dari ~150 baris), pertimbangkan untuk memecahnya. Prinsipnya: setiap komponen punya satu tanggung jawab yang jelas.
Kesimpulan
| Konsep | Cara Penggunaan |
|---|---|
| Function component | function Nama({ props }) { return <jsx/> } |
| Props | Atribut di JSX: <Comp nama="nilai" /> |
| Destructuring | function Comp({ nama, umur }) { ... } |
| Children | function Comp({ children }) { return <div>{children}</div> } |
| Default value | function Comp({ warna = "merah" }) { ... } |
Conditional (&&) | {kondisi && <Elemen />} |
| Conditional (ternary) | {kondisi ? <A /> : <B />} |
| List rendering | {items.map(item => <Li key={item.id} />)} |
Artikel sebelumnya: Mulai Cepat dengan React — setup project React dengan Vite.
Langkah selanjutnya: State dan Hooks di React — cara membuat UI yang interaktif dengan useState dan useEffect.