Reactjs Context Composition Prop Drilling
Definisi
Di React, data mengalir dari parent ke child lewat props. Pola ini sederhana, eksplisit, dan biasanya cukup untuk sebagian besar komponen. Saat kebutuhan UI mulai lebih dalam, kita punya dua opsi yang sering dipakai: composition dan Context.
- Composition: menyusun komponen dengan cara menyisipkan child, elemen, atau callback agar data tetap mengalir secara lokal.
- Context: menyediakan data dari satu titik agar bisa dibaca banyak komponen di bawahnya tanpa harus meneruskan props di setiap level.
- Prop drilling: kondisi saat props “dititipkan” lewat banyak komponen perantara hanya supaya sampai ke komponen yang benar-benar memakainya.
Kalau diringkas: prop drilling adalah gejala, composition adalah cara merapikan struktur, dan Context adalah alat berbagi data lintas level.
Kapan Prop Drilling Masih Wajar
Prop drilling bukan dosa. Dalam banyak kasus, ia justru pilihan paling jelas.
Gunakan props biasa kalau:
- data hanya dipakai oleh satu atau dua level komponen
- alur data masih mudah dibaca dari parent ke child
- komponen perantara memang bertugas meneruskan data itu
- perubahan state masih lokal dan tidak perlu dibagi luas
Contoh yang sehat:
function Page() {
const [query, setQuery] = useState('');
return <SearchPanel query={query} onQueryChange={setQuery} />;
}
function SearchPanel({ query, onQueryChange }) {
return <SearchInput value={query} onChange={onQueryChange} />;
}Di sini, query belum perlu Context. Rutenya masih pendek, dan setiap prop punya makna yang jelas.
Kapan Composition Cukup
Composition cocok saat masalahnya bukan “siapa yang bisa membaca data”, melainkan “bagaimana menyusun komponen tanpa membuat props berserakan”.
Pakai composition kalau:
- komponen perlu menerima isi fleksibel lewat
children - parent ingin menyisipkan UI khusus tanpa menambah banyak prop
- kita ingin menjaga komponen tetap generik dan reusable
- hubungan antarbagian lebih cocok diatur lewat struktur, bukan lewat state global
Contoh:
function Card({ children }) {
return <section className="card">{children}</section>;
}
function ProfilePage() {
return (
<Card>
<ProfileHeader />
<ProfileDetails />
</Card>
);
}Di sini, Card tidak perlu tahu isi internalnya. Composition menjaga komponen tetap kecil, fokus, dan mudah diganti.
Pola composition yang sering berguna
childrenuntuk menyisipkan konten bebas- slot pattern lewat props seperti
header,footer, atauactions - render props untuk memberi data ke child secara terarah
- compound components bila beberapa bagian UI memang satu keluarga
Composition biasanya lebih sehat daripada Context kalau masalahnya masih bisa diselesaikan di level struktur komponen.
Kapan Context Dipakai
Context dipakai saat ada data yang:
- dibutuhkan oleh banyak komponen di level berbeda
- sebenarnya global untuk satu area aplikasi, bukan seluruh app
- membuat prop drilling terlalu panjang dan tidak membantu pembacaan kode
- jarang berubah, atau perubahan-nya memang perlu menjangkau banyak consumer
Contoh data yang cocok:
- tema UI
- bahasa / locale
- autentikasi pengguna aktif
- preferensi tampilan yang dipakai lintas komponen
- konfigurasi yang berlaku untuk satu subtree aplikasi
Contoh data yang boleh memakai Context, tapi tetap harus hati-hati:
- state keranjang belanja
- filter global di satu halaman
- status sidebar terbuka/tutup
- object session pengguna
Alur kerja Context
Inti yang perlu diingat:
Context.Providermenaruh nilai untuk subtree di bawahnya.useContext()membaca nilai terbaru dari provider terdekat.- Saat value provider berubah, consumer yang bergantung pada context bisa ikut rerender.
Kenapa Context Tidak Selalu Lebih Baik
Context sering terlihat seperti jalan pintas yang rapi, tapi ada biaya tersembunyi.
Beberapa jebakan umum:
- Semua data dimasukkan ke context padahal cuma dipakai satu komponen.
- Context dijadikan tempat state kecil yang sebenarnya bisa tetap lokal.
- Satu context besar menampung banyak hal sehingga setiap perubahan kecil memicu consumer yang tidak perlu.
- Logika bisnis dan state UI dicampur dalam provider yang makin sulit diuji.
- Optimisasi datang terlalu dini, sebelum ada masalah nyata.
Kalau state masih kecil, context sering menambah kompleksitas tanpa mengurangi masalah.
Tanda state masih lebih baik lokal
Kalau jawabannya iya untuk sebagian besar poin ini, jangan buru-buru pakai Context:
- hanya dipakai satu fitur kecil
- komponen pemakai masih dekat secara struktur
- props yang diteruskan belum banyak
- alur baca masih jelas tanpa bantuan provider
- state itu bukan kebutuhan lintas subtree
Kapan Composition Lebih Baik daripada Context
Composition biasanya menang kalau yang ingin diselesaikan adalah hubungan parent-child yang konkret, bukan distribusi state lintas tree.
Pilih composition kalau:
- komponen cuma perlu “diisi” dengan UI lain
- data bisa diteruskan sebagai children atau slot
- kita ingin menghindari ketergantungan implisit dari consumer ke provider
- reuse komponen lebih penting daripada akses global
Contoh kasus: layout.
function Layout({ sidebar, content }) {
return (
<div className="layout">
<aside>{sidebar}</aside>
<main>{content}</main>
</div>
);
}Model seperti ini sering lebih enak dibaca daripada menaruh sidebar dan content ke context, karena struktur UI-nya memang eksplisit.
Perbandingan Cepat
| Pola | Cocok untuk | Kelebihan | Risiko |
|---|---|---|---|
| Props biasa | data pendek, jelas, lokal | paling eksplisit | prop drilling kalau terlalu dalam |
| Composition | UI fleksibel, reusable, struktur jelas | komponen tetap generik | bisa terlalu abstrak kalau dipaksa |
| Context | data lintas subtree | menghindari prop drilling | consumer jadi implisit, rerender bisa meluas |
Jebakan Global State Kecil yang Dibesarkan Terlalu Dini
Ini jebakan yang sering kejadian di proyek React:
- Ada state kecil, misalnya
isOpenatauselectedTab. - Karena terlihat “akan dipakai banyak tempat”, state itu langsung dipindahkan ke Context.
- Provider jadi lapisan baru yang belum tentu perlu.
- Lama-lama semua hal ikut masuk ke provider yang sama.
- Akhirnya, state kecil berubah jadi global state mini yang susah dirawat.
Masalah utamanya bukan Context-nya, tapi keputusan untuk mengglobalisasi sesuatu sebelum ada bukti kebutuhan.
Tanda-tandanya:
- provider ditempatkan terlalu tinggi tanpa alasan struktural
- satu context menampung state yang tidak saling berkaitan
- komponen bawah bergantung pada value implisit, bukan props yang terlihat
- sulit memahami kenapa rerender terjadi
- testing jadi lebih berat karena banyak setup provider
Prinsip amannya: naikkan state hanya sejauh perlu, bukan sejauh mungkin.
Contoh Keputusan Praktis
Kasus 1: Form kecil
Kalau state hanya dipakai di satu form, tetap lokal atau naikkan sedikit ke parent. Biasanya tidak perlu Context.
Kasus 2: Tema aplikasi
Kalau banyak komponen perlu tahu mode gelap/terang, Context masuk akal. Ini data global untuk satu subtree UI.
Kasus 3: Sidebar layout
Kalau hanya beberapa komponen dalam layout yang perlu tahu status sidebar, composition atau lifting state ke layout parent sering cukup. Context baru berguna kalau aksesnya benar-benar melewati banyak level.
Kasus 4: User session
Kalau banyak bagian app perlu tahu user aktif, role, atau status login, Context lebih masuk akal karena itu memang shared app state.
Pola Rekomendasi
Urutan berpikir yang aman biasanya begini:
- Mulai dari props biasa.
- Kalau komponen menjadi terlalu dalam, lihat apakah composition bisa merapikan struktur.
- Kalau data memang harus dibaca banyak komponen lintas subtree, baru pakai Context.
- Kalau Context mulai membengkak, pecah jadi beberapa context yang lebih kecil.
- Jangan jadikan Context tempat semua state.
Ringkasan Cepat
- Props: pilihan default.
- Composition: dipakai untuk struktur UI yang fleksibel dan reusable.
- Context: dipakai untuk shared data yang memang lintas subtree.
- Prop drilling: tidak selalu salah; sering hanya tanda bahwa struktur komponen perlu ditata ulang.
- Global state kecil yang dibesarkan terlalu dini: sering lebih mahal daripada problem yang ingin diselesaikan.
Referensi Terkait
- Component, Props, State, dan Render Flow
- Hooks Dasar React.js: useState, useEffect, useMemo, useCallback, dan useRef
- Forms React.js: Controlled vs Uncontrolled, Lifting State, Validation, dan Submit Flow
- Rendering Performance React.js: memo, useMemo, useCallback, React.memo, List Rendering, dan Key Stability