Reactjs Component Props State Render Flow
Definisi
Di React.js, UI dibangun dari component. Setiap component menerima data dari luar lewat props, menyimpan data lokal tertentu lewat state, lalu menghasilkan tampilan melalui proses render.
Kalau disederhanakan:
- component = unit UI yang bisa dipakai ulang
- props = data masuk dari parent ke child
- state = data internal yang berubah seiring interaksi atau waktu
- render flow = urutan bagaimana React menghitung ulang tampilan saat data berubah
Topik ini penting karena hampir semua keputusan arsitektur React berputar di sekitar empat hal itu.
Kapan dipakai
Gunakan pemahaman props dan state untuk membedakan:
- data yang datang dari luar komponen
- data yang perlu dikelola oleh komponen itu sendiri
- bagian UI yang harus ikut berubah saat data berubah
- batas pemecahan komponen yang sehat
Kalau batas ini kabur, komponen biasanya cepat membesar, state jadi tersebar, dan rerender terasa “random” padahal sebenarnya mengikuti alur data yang cukup jelas.
Struktur Dasar
Component
Component adalah fungsi atau kelas yang mengembalikan UI.
Dalam praktik modern, yang paling sering dipakai adalah function component.
function ProfileCard() {
return <div>Profile</div>;
}Component bisa dipecah jadi bagian kecil supaya:
- lebih mudah dibaca
- lebih mudah diuji
- lebih mudah dipakai ulang
- tanggung jawabnya tidak campur aduk
Props
Props adalah input untuk component.
Data ini mengalir dari parent ke child dan sifatnya read-only dari sudut pandang child.
function Greeting({ name }) {
return <p>Halo, {name}</p>;
}
function App() {
return <Greeting name="Alya" />;
}Di sini, App mengirim name ke Greeting. Greeting hanya membaca nilai itu, bukan mengubahnya.
Props cocok untuk data seperti:
- label tombol
- daftar item
- status dari parent
- handler event dari parent
- konfigurasi tampilan
State
State adalah data yang hidup di dalam component dan bisa berubah.
State dipakai saat component perlu menyimpan informasi yang memengaruhi render berikutnya.
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
Count: {count}
</button>
);
}State cocok untuk:
- nilai input form
- toggle buka/tutup
- hasil interaksi user
- data sementara yang berubah di sisi UI
- status loading, error, atau selected item
Cara Kerja Data Masuk Lewat Props
Props adalah jalur utama untuk mengalirkan data dari atas ke bawah.
Urutannya begini:
- parent menentukan nilai
- parent render child dengan props tertentu
- child menerima props sebagai argumen
- child menampilkan UI berdasarkan nilai itu
function UserRow({ user }) {
return <li>{user.name}</li>;
}
function UserList({ users }) {
return (
<ul>
{users.map((user) => (
<UserRow key={user.id} user={user} />
))}
</ul>
);
}Poin pentingnya:
- child tidak perlu tahu sumber data awalnya
- parent yang memutuskan nilai apa yang dikirim
- child jadi lebih mudah dipakai ulang karena bergantung pada input yang jelas
Props sering dipakai untuk membentuk komponen yang presentational: fokus pada tampilan, bukan pengambilan data.
Kapan State Dipakai
State dipakai kalau data tersebut:
- berubah karena interaksi user
- berubah karena proses internal component
- harus bertahan antar render
- memengaruhi output UI
Kalau data hanya lewat sebagai parameter tampilan, biasanya cukup pakai props.
Panduan cepat
- Props: data datang dari luar
- State: data dikelola di dalam component
- Derived value: hasil hitung dari props/state, biasanya tidak perlu state tambahan
Contoh yang sering keliru:
function Price({ amount }) {
const [formatted, setFormatted] = useState(`Rp ${amount}`);
return <p>{formatted}</p>;
}Kalau formatted hanya turunan dari amount, state di sini justru tidak perlu. Lebih aman dihitung langsung:
function Price({ amount }) {
return <p>Rp {amount}</p>;
}State tambahan yang tidak perlu sering jadi sumber bug sinkronisasi.
Kenapa Rerender Terjadi
Rerender terjadi saat React perlu menghitung ulang tampilan component karena ada perubahan pada input render.
Pemicunya yang umum:
- state berubah di component itu sendiri
- props berubah dari parent
- parent rerender, lalu child ikut dievaluasi ulang
- context berubah bila component membaca context tersebut
Yang penting dipahami: rerender bukan berarti DOM langsung ditulis ulang seluruhnya. React lebih dulu menjalankan ulang fungsi component untuk membandingkan hasil render, lalu memperbarui bagian yang memang berubah.
Alur sederhananya
Hal yang sering disalahpahami
- rerender bukan selalu berarti bug
- rerender bukan selalu berarti DOM diubah total
- rerender adalah mekanisme normal saat React menyelaraskan UI dengan data terbaru
Alur Render di Component Tree
Saat satu state berubah di parent, React biasanya mengevaluasi ulang parent terlebih dulu. Setelah itu, child yang berada di bawahnya juga bisa ikut dievaluasi karena parent mengirim props baru atau karena subtree-nya dipanggil ulang.
Diagram ini tidak berarti semua node selalu benar-benar mengubah DOM. Yang terjadi adalah React mengecek ulang hasil render dari jalur yang terdampak.
Jebakan Umum Saat Memecah Komponen
1. Memindahkan state terlalu cepat ke child
Kadang state dipindahkan ke child karena terlihat “lebih rapi”, padahal parent masih butuh mengendalikan data itu.
Akibatnya:
- data jadi sulit dibagikan
- komunikasi antar komponen makin rumit
- parent dan child saling bergantung lewat event tidak langsung
Kalau dua komponen perlu membaca nilai yang sama, biasanya state lebih aman ditempatkan di ancestor terdekat yang relevan.
2. Prop drilling berlebihan
Kalau data harus diteruskan melalui banyak level hanya untuk sampai ke satu child, struktur mulai terasa berat.
Contoh gejala:
propsbertambah panjang tanpa alasan jelas- component perantara hanya meneruskan data
- perubahan kecil di bawah memaksa banyak file ikut disentuh
Solusi bisa berupa:
- memindahkan state ke tingkat yang lebih pas
- memecah struktur dengan lebih bijak
- memakai context bila memang cocok
3. Menyimpan derived state tanpa perlu
Derived state adalah nilai yang sebenarnya bisa dihitung dari props atau state lain.
Kalau disimpan lagi sebagai state terpisah, risikonya:
- nilainya bisa tidak sinkron
- update jadi dobel
- logika render makin sulit diikuti
Kalau bisa dihitung saat render, biasanya lebih baik dihitung saat render.
4. Component jadi terlalu kecil tanpa tujuan
Memecah komponen memang bagus, tapi terlalu agresif juga bisa bikin struktur tidak enak dibaca.
Tanda-tandanya:
- satu file penuh wrapper tanpa logika
- nama component terlalu banyak untuk satu layar sederhana
- pembaca harus lompat-lompat hanya untuk memahami satu alur kecil
Prinsipnya: pecah berdasarkan tanggung jawab, bukan sekadar demi memecah.
5. Props dan state bercampur tanpa batas yang jelas
Komponen yang bagus biasanya punya peran jelas:
- props untuk input eksternal
- state untuk data internal
- event handler untuk mengirim perubahan ke atas
Kalau semua logic disebar ke mana-mana, flow data jadi sulit diprediksi.
Contoh Pola yang Sehat
function SearchPage() {
const [query, setQuery] = useState('');
return (
<div>
<SearchInput value={query} onChange={setQuery} />
<SearchResultList query={query} />
</div>
);
}
function SearchInput({ value, onChange }) {
return (
<input
value={value}
onChange={(e) => onChange(e.target.value)}
placeholder="Cari produk"
/>
);
}Di sini:
SearchPagemenyimpan statequerySearchInputmenerimavaluedanonChangelewat propsSearchResultListjuga membacaquerysebagai props
Pola ini membuat sumber data jelas: satu state utama, beberapa child yang membaca inputnya.
Catatan Implementasi
- Pakai props untuk data yang sifatnya dikirim dari parent.
- Pakai state untuk data yang berubah di dalam component dan memengaruhi UI.
- Jangan simpan nilai turunan sebagai state kalau bisa dihitung langsung.
- Rerender itu normal; fokuslah pada batas state dan bentuk props, bukan pada ketakutan terhadap rerender itu sendiri.
- Saat memecah komponen, pikirkan siapa pemilik data dan siapa yang perlu membaca data itu.
- Kalau sebuah child hanya meneruskan props tanpa nilai tambah, evaluasi lagi apakah batas komponennya sudah tepat.
- Gunakan handler sebagai jalur balik dari child ke parent ketika child perlu memicu perubahan.
Istilah
- Component: unit UI yang menghasilkan tampilan dari data tertentu.
- Props: input dari parent ke child.
- State: data internal yang bisa berubah.
- Render: proses React menghitung UI berdasarkan props dan state.
- Rerender: render ulang saat input render berubah.
- Derived state: data yang bisa dihitung dari data lain, jadi tidak selalu perlu disimpan.
- Prop drilling: props diteruskan melalui banyak lapisan hanya untuk mencapai komponen tertentu.