Belajar React dari Nol: Panduan Lengkap Komponen, Props, State, dan Hooks
Panduan lengkap belajar React untuk pemula — apa itu React, cara install dengan Vite, JSX, component, props dan state, useState dan useEffect, mini-project aplikasi catatan, kesalahan umum, dan FAQ.
Pembuat Hyper Sheets & BelajarWeb.dev
React adalah library JavaScript paling populer untuk membangun user interface. Dibuat oleh Facebook (Meta), React digunakan oleh perusahaan besar seperti Netflix, Airbnb, Discord, dan ratusan ribu website lainnya. Kalau kamu serius mau jadi frontend developer, cepat atau lambat kamu akan bertemu React — dan panduan ini akan menemani kamu dari nol sampai bisa membangun aplikasi pertamamu.
Artikel ini panjang, dan itu disengaja. Kamu akan belajar apa itu React dan kenapa ia begitu dominan, cara install React di komputermu, memahami JSX, component, props, state, sampai dua hooks paling penting: useState dan useEffect. Di tengah artikel kita akan membangun aplikasi catatan langkah demi langkah, lalu ditutup dengan daftar kesalahan umum pemula dan FAQ. Siapkan editor kode kamu — ini bukan artikel untuk dibaca sambil rebahan doang.
Apa Itu React?
React adalah library JavaScript open-source untuk membangun user interface (UI) berbasis komponen. Dirilis oleh Facebook pada tahun 2013, React memungkinkan kamu menyusun tampilan web dari potongan-potongan kecil bernama component yang bisa dipakai ulang. Alih-alih memanipulasi DOM secara manual seperti di vanilla JavaScript, kamu cukup mendeskripsikan tampilan yang kamu inginkan, dan React yang mengurus update-nya.
Penting dipahami sejak awal: React adalah library, bukan framework. Bedanya? Framework seperti Angular memberikan aturan lengkap untuk semua aspek aplikasi — routing, form, HTTP client, semuanya sudah ditentukan. React hanya fokus pada satu hal: merender UI. Untuk kebutuhan lain seperti navigasi antar halaman atau pengambilan data, kamu bebas memilih library tambahan. Fleksibilitas ini yang membuat React dipakai di mana-mana, dari landing page sederhana sampai aplikasi sekelas Instagram.
Kenapa React begitu populer? Beberapa alasan utamanya:
- Komponen reusable — Bangun UI dari potongan kecil yang bisa dipakai ulang. Tombol yang sama bisa muncul di 20 halaman tanpa copy-paste kode.
- Deklaratif — Kamu mendeskripsikan apa yang ingin ditampilkan berdasarkan data, bukan bagaimana langkah-langkah mengubah DOM. Kode jadi lebih mudah dibaca dan diprediksi.
- Virtual DOM — React menyimpan representasi UI di memori, membandingkannya saat data berubah, lalu hanya meng-update bagian halaman yang benar-benar berubah.
- Ekosistem raksasa — React Router, TanStack Query, Zustand, Next.js, dan ribuan library lain siap dipakai. Hampir semua masalah yang kamu temui sudah pernah dipecahkan orang lain.
- Permintaan kerja tinggi — React konsisten menjadi salah satu skill paling dicari di lowongan frontend developer, termasuk di Indonesia.
Kalau kamu ingin merasakan React sebelum install apa pun, ada materi interaktif apa itu React yang bisa langsung kamu coba di browser tanpa setup.
Apa yang Harus Dikuasai Sebelum Belajar React?
Sebelum belajar React, kamu wajib nyaman dengan HTML, CSS, dan JavaScript modern (ES6+). React tidak menggantikan tiga fondasi itu — ia dibangun di atasnya. Pemula yang kesulitan belajar React hampir selalu bermasalah bukan di React-nya, melainkan di JavaScript-nya.
Secara spesifik, pastikan kamu paham konsep-konsep JavaScript berikut, karena semuanya muncul terus-menerus di kode React:
// 1. Arrow function
const sapa = (nama) => `Halo, ${nama}!`
// 2. Destructuring — mengekstrak nilai dari object/array
const user = { nama: 'Budi', kota: 'Bandung' }
const { nama, kota } = user
// 3. Spread operator — menyalin array/object
const buah = ['apel', 'mangga']
const buahBaru = [...buah, 'jeruk'] // ['apel', 'mangga', 'jeruk']
// 4. Array methods: map, filter
const angka = [1, 2, 3, 4]
const genap = angka.filter(n => n % 2 === 0) // [2, 4]
const dobel = angka.map(n => n * 2) // [2, 4, 6, 8]
// 5. Template literals
const pesan = `${nama} tinggal di ${kota}`
Method map() dan filter() khususnya adalah roti sehari-hari di React — hampir setiap daftar data dirender dengan map(). Kalau masih ragu, luangkan waktu di latihan interaktif array methods sampai lancar. Untuk fondasi yang lebih menyeluruh, baca dulu panduan apa itu JavaScript dan belajar HTML untuk pemula di blog ini.
Kabar baiknya: kamu tidak perlu menguasai semua sudut JavaScript dulu. Paham variabel, fungsi, object, array, dan lima konsep di atas sudah cukup untuk mulai. Sisanya bisa kamu pelajari sambil jalan.
Cara Install React di Komputer Kamu
Cara install React paling direkomendasikan saat ini adalah menggunakan Vite, sebuah build tool modern yang cepat dan ringan. Kamu hanya butuh Node.js terpasang di komputer, lalu satu perintah di terminal untuk membuat proyek React lengkap. Create React App (CRA) yang dulu populer sudah tidak direkomendasikan lagi oleh tim React.
Langkah 1: Pastikan Node.js Terpasang
React project membutuhkan Node.js (runtime JavaScript di luar browser) dan npm (package manager yang otomatis ikut terinstall bersama Node.js). Cek dulu apakah keduanya sudah ada:
node -v
npm -v
Kalau muncul nomor versi (misalnya v22.x.x), kamu siap lanjut. Kalau muncul error “command not found”, download Node.js versi LTS dari situs resmi nodejs.org, install, lalu buka ulang terminal dan cek lagi.
Langkah 2: Buat Proyek React dengan Vite
Jalankan perintah berikut di terminal, di folder tempat kamu biasa menyimpan proyek:
npm create vite@latest aplikasi-catatan -- --template react
cd aplikasi-catatan
npm install
npm run dev
Penjelasan tiap baris:
npm create vite@latest aplikasi-catatan -- --template react— membuat folder proyek bernamaaplikasi-catatandengan template React. Tanda--di tengah itu penting saat pakai npm: ia meneruskan opsi--template reactke Vite.cd aplikasi-catatan— masuk ke folder proyek.npm install— mengunduh semua dependency (termasuk React itu sendiri) ke foldernode_modules.npm run dev— menjalankan development server. Buka alamat yang muncul di terminal (biasanyahttp://localhost:5173) dan kamu akan melihat halaman starter React.
Langkah 3: Kenali Struktur Proyek
Buka folder proyek di editor (VS Code sangat direkomendasikan). Strukturnya kurang lebih seperti ini:
aplikasi-catatan/
├── index.html ← satu-satunya file HTML
├── package.json ← daftar dependency & script
├── vite.config.js ← konfigurasi Vite
└── src/
├── main.jsx ← titik masuk aplikasi
├── App.jsx ← komponen utama
├── App.css
└── index.css
File index.html isinya sangat minim — hanya satu div kosong tempat React “menempel”:
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
Sedangkan src/main.jsx adalah tempat React mengambil alih div#root tersebut:
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import App from './App.jsx'
import './index.css'
createRoot(document.getElementById('root')).render(
<StrictMode>
<App />
</StrictMode>,
)
Dari titik ini, seluruh UI aplikasi kamu hidup di dalam komponen React, dimulai dari App. Kamu hampir tidak akan pernah menyentuh index.html lagi.
Satu catatan: kalau kamu belum bisa install apa pun (misalnya pakai komputer warnet atau HP), kamu tetap bisa belajar — semua konsep di artikel ini bisa dipraktikkan di playground online seperti StackBlitz atau CodeSandbox.
JSX Adalah: Sintaks HTML di Dalam JavaScript
JSX adalah ekstensi sintaks JavaScript yang memungkinkan kamu menulis markup mirip HTML langsung di dalam kode JavaScript. JSX bukan HTML sungguhan dan bukan string — saat build, ia diubah (di-transpile) menjadi pemanggilan fungsi JavaScript biasa. JSX-lah yang membuat kode React terasa natural: struktur UI dan logikanya hidup berdampingan di satu tempat.
Contoh paling sederhana:
const judul = <h1>Halo, Dunia!</h1>
Kelihatannya aneh — HTML kok di-assign ke variabel? Tapi ingat, ini bukan HTML. Di balik layar, baris itu dikompilasi menjadi pemanggilan fungsi yang menghasilkan object JavaScript biasa yang mendeskripsikan elemen h1.
Karena JSX pada dasarnya JavaScript, ada beberapa aturan yang berbeda dari HTML:
classmenjadiclassName— karenaclassadalah reserved keyword di JavaScript.formenjadihtmlFor— alasan yang sama.- Semua tag harus ditutup —
<img />,<br />,<input />. HTML memaafkan tag yang tidak ditutup; JSX tidak. - Satu elemen induk — sebuah komponen harus mengembalikan satu elemen pembungkus. Kalau tidak mau menambah
divekstra, pakai Fragment:<>...</>. - Expression JavaScript ditulis dalam kurung kurawal — apa pun di dalam
{ }dievaluasi sebagai JavaScript.
Poin terakhir adalah kekuatan super JSX. Perhatikan:
function Profil() {
const nama = 'Sinta'
const skills = ['HTML', 'CSS', 'JavaScript']
return (
<div className="profil">
<h1>Halo, saya {nama}</h1>
<p>Saya menguasai {skills.length} skill:</p>
<ul>
{skills.map(skill => (
<li key={skill}>{skill}</li>
))}
</ul>
<p>{skills.includes('React') ? 'Sudah bisa React!' : 'Sedang belajar React...'}</p>
</div>
)
}
Di satu blok kode kamu bisa menyisipkan variabel, memanggil method, melakukan perhitungan, sampai conditional dengan ternary operator. Yang tidak bisa ditulis di dalam kurung kurawal adalah statement seperti if, for, atau while — hanya expression yang menghasilkan nilai. Kalau butuh logika bercabang yang kompleks, tulis di atas return, simpan hasilnya di variabel, baru sisipkan ke JSX.
Kalau mau latihan menulis JSX dengan feedback langsung, cobalah pelajaran interaktif dasar-dasar JSX — kamu menulis kode dan hasilnya langsung dirender.
Component React: Balok Lego Penyusun UI
Component (komponen) adalah fungsi JavaScript yang mengembalikan JSX, dan merupakan unit dasar penyusun UI di React. Semua yang kamu lihat di aplikasi React — tombol, form, navbar, bahkan seluruh halaman — adalah komponen. Filosofinya seperti balok Lego: bangun potongan kecil yang fokus pada satu hal, lalu susun menjadi struktur besar.
Komponen paling sederhana:
function Greeting() {
return <h1>Halo, Dunia!</h1>
}
Dua aturan penting soal komponen:
- Nama komponen harus diawali huruf kapital.
<Greeting />dianggap komponen;<greeting />dianggap tag HTML biasa. Ini bukan konvensi opsional — React benar-benar membedakannya dari huruf pertamanya. - Komponen dipakai seperti tag HTML, lengkap dengan kemampuan self-closing:
<Greeting />.
Kekuatan sebenarnya muncul saat komponen disusun (komposisi):
function Header() {
return (
<header>
<h1>Toko Buku Online</h1>
</header>
)
}
function BookCard() {
return (
<article>
<h2>Judul Buku</h2>
<p>Deskripsi singkat buku.</p>
<button>Beli</button>
</article>
)
}
function App() {
return (
<div>
<Header />
<main>
<BookCard />
<BookCard />
<BookCard />
</main>
</div>
)
}
App tersusun dari Header dan tiga BookCard. Setiap komponen bisa dikembangkan, dites, dan diperbaiki secara terpisah. Saat aplikasi tumbuh dari 3 komponen menjadi 300, pola pikir ini yang menyelamatkan kamu dari kode spaghetti.
Tapi ada yang janggal di contoh di atas: ketiga BookCard menampilkan data yang sama persis. Bagaimana caranya satu komponen menampilkan data yang berbeda-beda? Jawabannya: props.
Props dan State: Dua Cara Data Hidup di React
Props dan state adalah dua mekanisme utama pengelolaan data di React: props adalah data yang dikirim dari komponen induk ke anak (read-only), sedangkan state adalah data internal komponen yang bisa berubah seiring waktu. Memahami perbedaan keduanya adalah gerbang untuk benar-benar “ngerti React”, karena hampir semua bug pemula berakar dari kebingungan di sini.
Props: Mengirim Data ke Komponen
Props (singkatan dari properties) dikirim ke komponen persis seperti atribut HTML, dan diterima sebagai parameter fungsi:
function BookCard({ judul, penulis, harga }) {
return (
<article>
<h2>{judul}</h2>
<p>oleh {penulis}</p>
<strong>Rp {harga.toLocaleString('id-ID')}</strong>
</article>
)
}
function App() {
return (
<main>
<BookCard judul="Laskar Pelangi" penulis="Andrea Hirata" harga={85000} />
<BookCard judul="Bumi Manusia" penulis="Pramoedya A.T." harga={120000} />
</main>
)
}
Sekarang satu komponen BookCard bisa menampilkan buku apa pun. Perhatikan harga={85000} — nilai selain string dikirim dengan kurung kurawal. Sintaks { judul, penulis, harga } di parameter adalah destructuring, cara paling umum menerima props.
Aturan emas: props bersifat read-only. Komponen anak tidak boleh (dan tidak bisa) mengubah props yang ia terima. Data mengalir satu arah, dari induk ke anak — ini yang disebut one-way data flow, dan inilah yang membuat aplikasi React mudah dilacak alurnya. Kamu bisa mendalami pola-pola pengiriman props di materi interaktif props di React.
State: Data yang Berubah dengan useState
Kalau props adalah data dari luar, state adalah data milik komponen itu sendiri yang bisa berubah — isi keranjang belanja, teks yang sedang diketik, status buka/tutup sebuah modal. Untuk membuat state, gunakan hook useState:
import { useState } from 'react'
function Counter() {
const [count, setCount] = useState(0)
return (
<div>
<p>Klik: {count}</p>
<button onClick={() => setCount(count + 1)}>
Tambah
</button>
</div>
)
}
Bedah baris const [count, setCount] = useState(0):
useState(0)membuat state dengan nilai awal0.- Ia mengembalikan array berisi dua hal: nilai state saat ini (
count) dan fungsi untuk mengubahnya (setCount). - Penamaan
[x, setX]adalah konvensi yang dipakai hampir semua kode React di dunia.
Setiap kali setCount dipanggil, React akan re-render komponen — menjalankan ulang fungsinya dengan nilai state terbaru, lalu meng-update DOM seperlunya. Kamu tidak pernah menyentuh DOM langsung; kamu mengubah data, dan UI mengikuti. Ini inti dari cara React bekerja.
Teori cukup — sekarang giliran kamu. Mainkan demo interaktif di bawah ini: klik counternya, tambah dan hapus todo-nya, dan perhatikan bagaimana UI selalu mengikuti state tanpa satu baris pun manipulasi DOM manual:
const [count, setCount] = useState(0)Semua yang barusan kamu mainkan hanya menggunakan useState. Kalau mau membedahnya lebih dalam sambil praktik, lanjutkan ke latihan interaktif useState.
Props vs State: Tabel Perbandingan
| Props | State | |
|---|---|---|
| Siapa yang mengatur? | Komponen induk | Komponen itu sendiri |
| Bisa diubah? | Tidak (read-only) | Ya (via setter function) |
| Kapan berubah? | Saat induk mengirim nilai baru | Saat fungsi setter dipanggil |
| Analogi | Parameter fungsi | Variabel lokal yang “diingat” React |
Cara cepat memutuskan: kalau data itu diberikan dari luar, ia props. Kalau data itu lahir dan berubah di dalam komponen karena interaksi pengguna, ia state.
useState dan useEffect: Dua Hooks yang Wajib Kamu Kuasai
Hooks adalah fungsi khusus berawalan use yang memberi komponen fungsi akses ke fitur React seperti state dan lifecycle, dan dua yang paling fundamental adalah useState dan useEffect. useState untuk menyimpan data yang berubah, useEffect untuk menjalankan side effect seperti fetch data atau sinkronisasi dengan sistem di luar React. Menguasai keduanya berarti kamu sudah bisa membangun mayoritas fitur aplikasi nyata.
useState Lebih Dalam
useState bisa menyimpan tipe data apa pun — angka, string, boolean, array, object:
const [items, setItems] = useState([])
const [isOpen, setIsOpen] = useState(false)
const [form, setForm] = useState({ nama: '', email: '' })
Ada satu aturan yang sering menjebak pemula: jangan pernah memutasi state secara langsung. React mendeteksi perubahan dengan membandingkan referensi object/array lama dan baru. Kalau kamu mengubah isinya tanpa membuat yang baru, React menganggap tidak ada perubahan dan tidak me-render ulang:
// ❌ SALAH — memutasi array lama, UI tidak update
items.push('baru')
setItems(items)
// ✅ BENAR — membuat array baru dengan spread operator
setItems([...items, 'baru'])
// ✅ BENAR — update sebagian object
setForm({ ...form, nama: 'Budi' })
Satu jurus penting lagi: functional update. Kalau nilai baru bergantung pada nilai lama, kirim fungsi ke setter, bukan nilai langsung:
// Lebih aman saat update beruntun
setCount(prev => prev + 1)
Kenapa ini penting? Kita bahas di bagian kesalahan umum nanti.
useEffect: Menjalankan Side Effect
Komponen React idealnya “murni”: menerima props/state, mengembalikan JSX. Tapi aplikasi nyata butuh hal-hal di luar itu — mengambil data dari API, mengubah judul tab browser, memasang event listener, menyimpan ke localStorage. Semua itu disebut side effect, dan tempatnya di useEffect:
import { useState, useEffect } from 'react'
function UserProfile({ userId }) {
const [user, setUser] = useState(null)
useEffect(() => {
fetch(`https://api.contoh.com/users/${userId}`)
.then(res => res.json())
.then(data => setUser(data))
}, [userId]) // ← dependency array
if (!user) return <p>Loading...</p>
return <h1>{user.name}</h1>
}
Bagian paling krusial adalah dependency array — argumen kedua useEffect yang mengontrol kapan effect dijalankan ulang:
[](array kosong) — effect hanya jalan sekali setelah komponen pertama kali muncul (mount).[userId]— effect jalan saat mount, dan setiap kaliuserIdberubah.- Tanpa array sama sekali — effect jalan setelah setiap render. Hampir tidak pernah kamu butuhkan, dan sering jadi sumber bug.
Kombinasi nilai di dependency array ini sering membingungkan di awal. Cara tercepat memahaminya adalah bereksperimen langsung di playground dependency array useEffect — kamu bisa mengubah dependency dan melihat kapan effect terpicu secara visual.
useEffect juga bisa mengembalikan fungsi cleanup, yang dijalankan sebelum effect berikutnya atau saat komponen dilepas dari layar. Wajib dipakai saat kamu memasang sesuatu yang perlu dibereskan, seperti timer atau event listener:
useEffect(() => {
const timer = setInterval(() => {
console.log('tick')
}, 1000)
return () => clearInterval(timer) // cleanup: hentikan timer
}, [])
Tanpa cleanup, setiap kali komponen muncul-hilang-muncul, timer baru terus menumpuk — memory leak klasik.
useRef: Bonus Hook Ketiga
Satu hook lagi yang sering kamu butuhkan: useRef, untuk mengakses elemen DOM langsung atau menyimpan nilai yang tidak memicu re-render:
import { useRef } from 'react'
function SearchInput() {
const inputRef = useRef(null)
function focusInput() {
inputRef.current.focus()
}
return (
<div>
<input ref={inputRef} placeholder="Cari..." />
<button onClick={focusInput}>Focus</button>
</div>
)
}
Berbeda dengan state, mengubah ref.current tidak menyebabkan re-render. Pakai ref untuk hal-hal “di pinggir” React: fokus input, scroll ke elemen, menyimpan id timer.
Praktik: Membangun Aplikasi Catatan Langkah demi Langkah
Cara terbaik memahami React adalah membangun sesuatu yang utuh, dan aplikasi catatan adalah proyek pertama yang ideal: cukup sederhana untuk diselesaikan sekali duduk, tapi menyentuh semua konsep inti. Kita akan memakai component, JSX, props, state, event handling, list rendering, sampai useEffect untuk menyimpan data ke localStorage. Buka proyek aplikasi-catatan yang kamu buat di bagian install tadi.
Langkah 1: Bersihkan Template
Hapus isi src/App.jsx dan ganti dengan kerangka kosong:
import './App.css'
function App() {
return (
<div className="app">
<h1>Catatan Saya</h1>
</div>
)
}
export default App
Ganti juga seluruh isi src/App.css dengan style sederhana ini:
.app {
max-width: 480px;
margin: 40px auto;
font-family: system-ui, sans-serif;
}
form {
display: flex;
gap: 8px;
margin-bottom: 20px;
}
form input {
flex: 1;
padding: 8px 12px;
border: 1px solid #ccc;
border-radius: 6px;
}
ul {
list-style: none;
padding: 0;
}
li {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 4px;
border-bottom: 1px solid #e5e5e5;
}
.kosong {
color: #888;
font-style: italic;
}
Simpan, dan halaman di browser langsung berubah — Vite melakukan hot reload otomatis.
Langkah 2: State untuk Daftar Catatan dan Input
Aplikasi kita butuh dua state: daftar catatan (array of object) dan teks yang sedang diketik di input:
import { useState } from 'react'
import './App.css'
function App() {
const [notes, setNotes] = useState([])
const [text, setText] = useState('')
function handleSubmit(e) {
e.preventDefault()
if (text.trim() === '') return
const newNote = {
id: crypto.randomUUID(),
text: text.trim(),
}
setNotes([newNote, ...notes])
setText('')
}
return (
<div className="app">
<h1>Catatan Saya</h1>
<form onSubmit={handleSubmit}>
<input
value={text}
onChange={(e) => setText(e.target.value)}
placeholder="Tulis catatan baru..."
/>
<button type="submit">Simpan</button>
</form>
</div>
)
}
export default App
Beberapa hal yang terjadi di sini:
- Controlled input — nilai input dikontrol state:
value={text}menampilkan state,onChangemeng-update state setiap ketikan. Ini pola standar form di React. e.preventDefault()mencegah browser me-reload halaman saat form disubmit (perilaku default HTML).crypto.randomUUID()menghasilkan id unik untuk tiap catatan — API bawaan browser modern, tanpa library tambahan.setNotes([newNote, ...notes])membuat array baru berisi catatan baru di depan, diikuti semua catatan lama. Ingat: tidak bolehnotes.push().
Langkah 3: Render Daftar Catatan
Sekarang tampilkan isinya. Tambahkan di bawah </form>, masih di dalam div.app:
{notes.length === 0 ? (
<p className="kosong">Belum ada catatan. Tulis yang pertama!</p>
) : (
<ul>
{notes.map(note => (
<li key={note.id}>{note.text}</li>
))}
</ul>
)}
Dua pola penting sekaligus:
- Conditional rendering dengan ternary: kalau daftar kosong, tampilkan pesan; kalau tidak, tampilkan list.
- List rendering dengan
.map(): setiap object catatan diubah menjadi elemenli. Atributkey={note.id}wajib — React memakainya untuk melacak item mana yang berubah, ditambah, atau dihapus antar render.
Coba di browser: ketik sesuatu, tekan Enter, dan catatanmu muncul. Kamu baru saja membangun alur data lengkap React: event → state → UI.
Langkah 4: Fitur Hapus
Tambahkan fungsi ini di dalam App, di bawah handleSubmit:
function handleDelete(id) {
setNotes(notes.filter(note => note.id !== id))
}
Lalu update bagian li agar punya tombol hapus:
<li key={note.id}>
{note.text}
<button onClick={() => handleDelete(note.id)}>Hapus</button>
</li>
filter() mengembalikan array baru tanpa catatan yang id-nya cocok — lagi-lagi immutable update. Perhatikan juga onClick={() => handleDelete(note.id)}: kita membungkusnya dalam arrow function karena perlu mengirim argumen. Kalau ditulis onClick={handleDelete(note.id)} (tanpa arrow), fungsi langsung dieksekusi saat render — bug klasik pemula.
Langkah 5: Simpan ke localStorage dengan useEffect
Saat ini, refresh halaman menghapus semua catatan. Mari perbaiki dengan localStorage. Ubah bagian atas komponen:
import { useState, useEffect } from 'react'
import './App.css'
function App() {
const [notes, setNotes] = useState(() => {
const saved = localStorage.getItem('catatan')
return saved ? JSON.parse(saved) : []
})
const [text, setText] = useState('')
useEffect(() => {
localStorage.setItem('catatan', JSON.stringify(notes))
}, [notes])
// ...sisanya sama
Dua teknik baru:
- Lazy initial state —
useState(() => ...)menerima fungsi yang hanya dijalankan sekali saat mount. Kita pakai untuk membaca localStorage tanpa membacanya ulang di setiap render. - useEffect dengan dependency
[notes]— setiap kali daftar catatan berubah, effect menyimpan versi terbarunya ke localStorage. Sinkronisasi state React dengan sistem eksternal: persis untuk inilahuseEffectada.
Selesai! Kamu punya aplikasi catatan fungsional dengan data yang bertahan setelah refresh. Sebagai tantangan lanjutan, coba tambahkan sendiri: fitur edit catatan, tombol “hapus semua” dengan konfirmasi, atau penanda waktu di tiap catatan. Kalau mau proyek terpandu yang lebih besar, ada proyek React interaktif yang menggabungkan semua materi dasar menjadi satu aplikasi utuh.
Kesalahan Umum Pemula React (dan Cara Menghindarinya)
Kesalahan pemula React hampir selalu berkisar pada lima hal: memutasi state langsung, salah memakai key, dependency array yang keliru, mengira setState langsung berubah, dan melanggar aturan hooks. Kabar baiknya, semuanya punya pola yang mudah dikenali. Berikut daftarnya, supaya kamu tidak perlu jatuh ke lubang yang sama.
1. Memutasi State Secara Langsung
Sudah disinggung di atas, tapi saking seringnya terjadi, ia layak diulang:
// ❌ UI tidak akan update
todos.push(todoBaru)
setTodos(todos)
// ✅ Selalu buat array/object baru
setTodos([...todos, todoBaru])
Gejalanya khas: “datanya berubah kalau di-console.log, tapi tampilannya nggak update”. Kalau kamu mengalami itu, hampir pasti ada mutasi langsung di suatu tempat.
2. Memakai Index Array sebagai Key
key={index} memang menghilangkan warning, tapi menimbulkan bug saat daftar bisa berubah urutan atau dihapus dari tengah — React jadi salah mencocokkan item lama dan baru, dan state komponen bisa “nyangkut” di item yang salah:
// ⚠️ Berisiko kalau list bisa berubah urutan/dihapus
{todos.map((todo, index) => <li key={index}>{todo.text}</li>)}
// ✅ Pakai id yang stabil dan unik
{todos.map(todo => <li key={todo.id}>{todo.text}</li>)}
3. useEffect yang Menjadi Infinite Loop
Meng-update state di dalam effect yang bergantung pada state itu sendiri — atau tanpa dependency array — menciptakan lingkaran setan: render → effect → setState → render → effect → dan seterusnya:
// ❌ Infinite loop: tanpa dependency array,
// effect jalan tiap render, dan setState memicu render lagi
useEffect(() => {
setCount(count + 1)
})
Solusinya: selalu tulis dependency array secara sadar, dan tanya dirimu “kapan sebenarnya effect ini perlu jalan ulang?“.
4. Mengira State Langsung Berubah Setelah setState
Ini yang paling bikin pemula garuk-garuk kepala:
function handleClick() {
setCount(count + 1)
setCount(count + 1)
setCount(count + 1)
// Hasil akhir: count hanya bertambah 1, bukan 3!
}
Kenapa? count di dalam fungsi itu adalah nilai dari render saat ini — snapshot. Ketiga baris sama-sama menghitung nilaiLama + 1. React juga mem-batch update dalam satu event handler. Solusinya functional update:
setCount(prev => prev + 1)
setCount(prev => prev + 1)
setCount(prev => prev + 1)
// Sekarang benar bertambah 3
Konsep batching dan snapshot ini jauh lebih gampang dipahami secara visual — coba playground batching useState untuk melihat kapan React menggabungkan beberapa update jadi satu render.
5. Memanggil Hooks Secara Kondisional
Hooks punya satu aturan keras: selalu dipanggil di level teratas komponen, tidak boleh di dalam if, loop, atau setelah return lebih awal:
// ❌ Melanggar Rules of Hooks
if (isLoggedIn) {
const [profile, setProfile] = useState(null)
}
// ✅ Hook di atas, kondisinya di logika/JSX
const [profile, setProfile] = useState(null)
if (!isLoggedIn) return <LoginPage />
React mengandalkan urutan pemanggilan hooks yang konsisten di setiap render untuk mencocokkan state dengan hook-nya. Hook di dalam kondisi merusak urutan itu.
Langkah Selanjutnya Setelah Menguasai Dasar
Setelah nyaman dengan component, props, state, dan dua hooks utama, jalur belajar React berikutnya adalah routing, data fetching, state management, lalu TypeScript dan framework full-stack. Jangan buru-buru — tiap tahap paling efektif dipelajari saat kamu benar-benar membutuhkannya di proyek.
Urutan yang saya rekomendasikan:
- React Router — navigasi antar halaman di aplikasi single-page.
- Data fetching yang serius — mulai dari
fetchdiuseEffect, lalu naik ke TanStack Query untuk caching dan sinkronisasi data server. - State management — Context API untuk kebutuhan ringan; Zustand atau Redux saat state global mulai kompleks.
- Custom hooks — mengekstrak logika yang berulang (misalnya
useLocalStorage) menjadi hook buatan sendiri. - TypeScript — type safety yang membuat refactoring aman dan autocomplete jadi luar biasa. Mulai dari panduan TypeScript untuk JavaScript developer.
- Next.js atau framework full-stack lain — server-side rendering, routing berbasis file, dan API route di atas fondasi React.
Untuk urusan styling, banyak tim React memilih utility-first CSS — kalau penasaran, baca panduan Tailwind CSS yang membahasnya dari nol.
React punya kurva belajar, tapi konsep-konsep dasarnya (component, props, state, hooks) akan selalu relevan apa pun framework yang kamu pakai nanti. Kuasai fundamentalnya, dan semua yang dibangun di atasnya akan terasa jauh lebih mudah.
FAQ Seputar Belajar React
Apa itu React dan apa bedanya dengan React Native?
React adalah library JavaScript untuk membangun user interface di web (berjalan di browser). React Native adalah framework terpisah yang memakai konsep dan sintaks React yang sama untuk membangun aplikasi mobile native Android dan iOS. Kalau kamu sudah menguasai React, belajar React Native jauh lebih cepat karena component, props, state, dan hooks-nya identik — yang berbeda hanya elemen dasarnya (View dan Text menggantikan div dan p).
Apakah belajar React harus menguasai JavaScript dulu?
Ya, minimal dasar-dasarnya. Kamu tidak perlu jadi ahli, tapi wajib nyaman dengan variabel, fungsi, object, array, arrow function, destructuring, dan array methods seperti map dan filter. React adalah JavaScript — kesulitan di React 90% adalah kesulitan JavaScript yang menyamar. Kalau fondasimu masih goyah, mundur sebentar ke materi JavaScript justru mempercepat perjalananmu.
React itu library atau framework?
Secara teknis React adalah library, karena ia hanya menangani lapisan UI dan tidak memaksakan struktur untuk routing, data fetching, atau build. Dalam percakapan sehari-hari (dan lowongan kerja) ia sering disebut “framework”, dan itu tidak masalah. Yang jelas: untuk aplikasi lengkap, React biasanya dipadukan dengan library lain, atau dipakai lewat framework seperti Next.js.
Berapa lama waktu yang dibutuhkan untuk bisa React?
Tergantung fondasi JavaScript dan konsistensi latihanmu, jadi tidak ada angka pasti. Sebagai gambaran kasar: dengan latihan rutin, konsep dasar (component, props, state, useState, useEffect) bisa dipahami dalam hitungan minggu, dan kepercayaan diri membangun proyek nyata datang setelah kamu menyelesaikan beberapa aplikasi kecil. Kuncinya bukan kecepatan, tapi membangun proyek — satu aplikasi catatan yang kamu tulis sendiri mengajarkan lebih banyak daripada sepuluh video tutorial yang hanya ditonton.
Kenapa useEffect saya jalan dua kali?
Kalau ini terjadi saat development, itu normal dan disengaja. Template Vite membungkus aplikasi dengan StrictMode, dan di mode development React sengaja me-mount komponen dua kali untuk membantumu menemukan effect yang tidak punya cleanup dengan benar. Di build production, effect hanya jalan sekali. Jangan hapus StrictMode untuk “memperbaiki” ini — perbaiki effect-nya agar aman dijalankan ulang.
Apakah masih perlu belajar class component?
Untuk memulai, tidak. React modern sepenuhnya berbasis function component dan hooks — semua dokumentasi resmi terbaru, library populer, dan codebase baru memakainya. Class component cukup kamu kenali sekilas agar tidak bingung saat menemui kode lama di proyek warisan, tapi jangan jadikan prioritas belajar.
Selamat — kalau kamu mengikuti artikel ini sambil praktik, kamu sudah melewati bagian tersulit dari belajar React: memulai. Simpan halaman ini sebagai referensi, selesaikan tantangan di mini-project tadi, dan teruslah membangun. Sampai jumpa di artikel berikutnya!