Komposisi Komponen — React

Di banyak bahasa OOP (Java, C#), pattern "extends" populer — ClassA extends ClassB, dapat semua method ClassB plus tambah sendiri. React MENOLAK pattern ini…

Komposisi artinya membangun komponen besar dengan menaruh komponen lain di dalamnya, bukan dengan mewarisi komponen lain. Alatnya ada dua: prop khusus children dan prop biasa yang isinya JSX. Bayangin bingkai foto. Bingkainya memberi pinggiran dan gaya, fotonya bebas kamu selipkan. Satu model bingkai bisa dipakai untuk foto apa pun, dan bingkainya gak perlu tahu foto siapa yang ada di dalamnya. Di React, Card adalah bingkainya, dan children adalah fotonya.

🧪 Tebakan cepat: Card menerima children, tapi return-nya cuma <div className="card"></div>. Kalau App menulis <Card><p>Konten kartu</p></Card>, apa yang tampil: paragraf "Konten kartu" atau kotak kosong? Tebak dulu, jawabannya ada di bagian "children: isi di antara tag".

children: isi di antara tag

function Card({ children }) {
  return <div className="card">{children}</div>
}

function App() {
  return (
    <Card>
      <p>Konten kartu</p>
    </Card>
  )
}

Hasilnya di halaman:

<div class="card">
  <p>Konten kartu</p>
</div>

Slot bernama: prop yang isinya JSX

function Layout({ header, children }) {
  return (
    <div>
      <header className="layout-header">{header}</header>
      <main className="layout-content">{children}</main>
    </div>
  )
}

function App() {
  return (
    <Layout header={<h1>Selamat Datang</h1>}>
      <p>Ini konten utama</p>
    </Layout>
  )
}

Hasilnya di halaman:

<div>
  <header class="layout-header"><h1>Selamat Datang</h1></header>
  <main class="layout-content"><p>Ini konten utama</p></main>
</div>

Komposisi menggantikan prop drilling

Prop drilling artinya mengoper prop lewat komponen yang gak memakainya, cuma supaya sampai ke komponen di bawahnya. Misalnya foto profil Rina di header:

function Avatar({ user }) {
  return <p>{user.nama}</p>
}

// Header gak memakai user, cuma meneruskannya ke Avatar
function Header({ user }) {
  return <header className="layout-header"><Avatar user={user} /></header>
}

// Layout juga gak memakai user, cuma meneruskannya ke Header
function Layout({ user, children }) {
  return (
    <div>
      <Header user={user} />
      <main className="layout-content">{children}</main>
    </div>
  )
}

App menulis <Layout user={user}>, dan user turun dua tingkat lewat komponen yang cuma jadi pipa. Dengan slot, App membuat Avatar sendiri lalu menitipkannya ke Layout yang tadi, yang punya slot header:

function App() {
  const user = { nama: 'Rina' }

  return (
    <Layout header={<Avatar user={user} />}>
      <Card>
        <p>Konten kartu</p>
      </Card>
    </Layout>
  )
}

Sekarang Layout gak tahu apa-apa soal user, dan Header gak dibutuhkan lagi. Kalau Avatar butuh data baru, cuma App dan Avatar yang berubah.

Kenapa React memilih komposisi

Di banyak bahasa, komponen "versi khusus" dibuat dengan inheritance (pewarisan): class SpecialCard extends Card mewarisi semua isi Card lalu menambah sendiri. React menyarankan komposisi, karena lebih fleksibel: pembungkus menerima JSX apa pun lewat children dan slot, dan tiap bagian bisa diganti tanpa mengubah komponen lain. Untuk versi khusus, cukup bungkus:

function Dialog({ title, children }) {
  return (
    <div className="dialog">
      <h2>{title}</h2>
      {children}
    </div>
  )
}

function ConfirmDialog({ children }) {
  return <Dialog title="Konfirmasi">{children}</Dialog>
}

ConfirmDialog adalah Dialog yang judulnya sudah diisi. Gak ada extends, cuma membungkus dan meneruskan children.

⚠️ Jebakan yang sering ketemu

TL;DR: Komposisi membangun komponen dengan menaruh komponen lain di dalamnya. children adalah prop khusus berisi apa pun di antara tag pembuka dan penutup, dan komponen pembungkus menaruhnya dengan {children}, misalnya <div className="card">{children}</div>. Untuk lebih dari satu tempat, kirim JSX lewat prop biasa (slot), misalnya <Layout header={<h1>Selamat Datang</h1>}>. Slot juga menghindari prop drilling: komponen di tengah gak perlu meneruskan data yang gak mereka pakai. React memilih komposisi daripada inheritance karena lebih fleksibel.

Yang akan kamu pelajari