Langsung ke konten
KamusNgoding
Pemula React 3 menit baca

Komponen dan Props di React: Membangun UI yang Reusable

#react #komponen #props #jsx #children #conditional-rendering #map #key

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 key penting? React menggunakan key untuk 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

KonsepCara Penggunaan
Function componentfunction Nama({ props }) { return <jsx/> }
PropsAtribut di JSX: <Comp nama="nilai" />
Destructuringfunction Comp({ nama, umur }) { ... }
Childrenfunction Comp({ children }) { return <div>{children}</div> }
Default valuefunction 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.

Artikel Terkait