Skip to content

Pola React: Compound Component Pattern

Posted on:January 12, 2026 at 10:00 AM

Halo, Sobat Ngoding! 👋

Pernah nggak sih kamu coba bikin komponen yang bisa dipake ulang (reusable), kayak Tabs atau Accordion, tapi ujung-ujungnya malah ribet sendiri karena harus ngoper banyak banget props?

Jadinya malah kayak gini nih, serem:

// Pendekatan "God Component"
<Tabs
  data={[
    { label: "Beranda", content: "Selamat datang!" },
    { label: "Profil", content: "Profil user di sini." }
  ]}
  theme="dark"
  activeTabIndex={0}
  onTabChange={handleTabChange}
  tabClassName="text-bold"
  panelClassName="p-4"
/>

Jalan sih jalan, tapi kaku banget. Gimana kalau kamu mau nambahin ikon di satu tab aja? Atau mau disable tab kedua? Kamu harus ngubah struktur datanya lagi. Ribet kan? 🤯

Kenalin nih, Compound Component Pattern.

Apaan tuh?

Inget tag HTML standar kayak <select> dan <option>? Mereka nggak kerja sendiri-sendiri, tapi kerjasama.

<select>
  <option value="1">Pilihan 1</option>
  <option value="2">Pilihan 2</option>
</select>

Si <select> yang ngatur state-nya, terus si <option> yang nampilin pilihannya. Mereka berbagi state secara implisit (diam-diam). Kita bisa lho bikin yang kayak gini di React!

Langkah 1: Bikin Context-nya

Pertama, kita butuh cara biar si induk (Tabs) bisa ngobrol sama anak-anaknya (Tab dan TabPanel) tanpa harus ngoper props satu-satu. Kita pake React Context buat ini.

import React, { createContext, useContext, useState } from 'react';

// 1. Bikin Context
const TabsContext = createContext();

// 2. Bikin Komponen Induk (Parent)
const Tabs = ({ children, defaultIndex = 0 }) => {
  const [activeIndex, setActiveIndex] = useState(defaultIndex);

  return (
    <TabsContext.Provider value={{ activeIndex, setActiveIndex }}>
      <div className="tabs-container">
        {children}
      </div>
    </TabsContext.Provider>
  );
};

Di sini, Tabs megang state (activeIndex) dan nyediain itu buat siapa aja yang ada di dalemnya.

Langkah 2: Bikin Sub-Komponennya

Sekarang, ayo kita bikin komponen-komponen yang bakal make context ini.

// 3. Bikin List Tab (pembungkus opsional buat styling)
const TabList = ({ children }) => {
  return <div className="flex border-b">{children}</div>;
};

// 4. Bikin Tab individunya
const Tab = ({ index, children }) => {
  const { activeIndex, setActiveIndex } = useContext(TabsContext);
  const isActive = activeIndex === index;

  return (
    <button
      onClick={() => setActiveIndex(index)}
      className={`p-2 ${isActive ? 'border-b-2 border-blue-500 font-bold' : 'text-gray-500'}`}
    >
      {children}
    </button>
  );
};

// 5. Bikin Panel Kontennya
const TabPanel = ({ index, children }) => {
  const { activeIndex } = useContext(TabsContext);

  if (activeIndex !== index) return null;

  return <div className="p-4">{children}</div>;
};

Langkah 3: Pake Deh!

Coba liat deh, API komponen kita jadi bersih dan fleksibel banget:

const App = () => {
  return (
    <Tabs defaultIndex={0}>
      <TabList>
        <Tab index={0}>🏠 Beranda</Tab>
        <Tab index={1}>👤 Profil</Tab>
        <Tab index={2}>⚙️ Pengaturan</Tab>
      </TabList>

      <TabPanel index={0}>
        <h2>Selamat Datang di Dashboard</h2>
        <p>Ini pake teknik Compound Component lho!</p>
      </TabPanel>
      <TabPanel index={1}>
        <UserProfile />
      </TabPanel>
      <TabPanel index={2}>
        <p>Pengaturan ada di sini...</p>
      </TabPanel>
    </Tabs>
  );
};

Kenapa ini lebih oke?

  1. Fleksibilitas: Saya bisa gampang nuker urutan tab, ngebungkus pake div lain buat styling, atau nambah ikon tanpa ngubah logika Tabs-nya.
  2. Keterbacaan: Kodenya keliatan kayak HTML biasa. Strukturnya langsung jelas.
  3. Pemisahan Tugas: Tabs ngurusin logika (state), sementara Tab dan TabPanel ngurusin tampilan.

Kapan harus pake?

Pake pola ini kalau kamu punya sekumpulan komponen yang perlu berbagi state dan logika secara implisit, contohnya:

Penutup

Compound Component pattern ini alat yang ampuh banget di React. Ini mindahin kerumitan dari si pemakai (kamu saat ini) ke si pembuat library (kamu juga, tapi versi masa depan).

Mulai deh pake ini buat komponen UI kamu, dijamin diri kamu di masa depan bakal berterima kasih!

Selamat Ngoding! 🚀