Bab 1: Quick Start — Kenalan Sama React

7 menit baca

Apa Itu React?

Bayangin kamu lagi main LEGO. Setiap balok LEGO punya bentuk dan fungsi sendiri — ada yang jadi atap, ada yang jadi dinding, ada yang jadi jendela. Kamu tinggal rakit balok-balok itu jadi rumah, kastil, atau apapun yang kamu mau.

React itu LEGO-nya web development.

Setiap "balok" di React disebut Component. Satu component bisa jadi tombol, bisa jadi navbar, bisa jadi satu halaman penuh. Kamu bikin component kecil-kecil, terus rakit jadi website utuh.

Kenapa React?

  • Reusable — Bikin component sekali, pakai berkali-kali. Tombol "Beli" yang sama bisa muncul di 50 halaman berbeda.
  • Terstruktur — Kode kamu rapi karena setiap bagian UI punya "rumahnya" sendiri.
  • Cepat — React cuma update bagian yang berubah, bukan seluruh halaman (ini namanya Virtual DOM).
  • Populer — Instagram, Facebook, Netflix, Tokopedia, Gojek — semua pakai React.

Membuat Component Pertama

Component di React itu cuma fungsi JavaScript yang return markup (HTML). Sesimpel itu.

jsx
function Tombol() {
  return (
    <button>Klik Saya</button>
  );
}

Coba sendiri: Edit kode di bawah dan lihat hasilnya langsung!

Itu udah component! Namanya Tombol. Dia return satu elemen <button>.

Aturan Penting

  1. Nama component HARUS huruf kapitalTombol ✅, tombol
  2. Return-nya harus satu elemen pembungkus — kalau mau return banyak elemen, bungkus pakai <div> atau <>...</>
jsx
// ❌ SALAH — return 2 elemen tanpa pembungkus
function Profil() {
  return (
    <h1>Yazid</h1>
    <p>Web Developer</p>
  );
}

// ✅ BENAR — dibungkus Fragment (<>...</>)
function Profil() {
  return (
    <>
      <h1>Yazid</h1>
      <p>Web Developer</p>
    </>
  );
}

Kenapa Harus Huruf Kapital?

React membedakan component buatan kamu vs tag HTML biasa berdasarkan huruf pertama:

  • <button> → React anggap ini tag HTML biasa
  • <Tombol> → React anggap ini component buatan kamu

Kalau kamu tulis <tombol>, React bakal cari tag HTML bernama "tombol" — yang tentu nggak ada. Hasilnya: error.


Menyusun Component (Nesting)

Kekuatan React ada di komposisi — component bisa dipanggil di dalam component lain.

jsx
function Tombol() {
  return <button>Klik Saya</button>;
}

function Halaman() {
  return (
    <div>
      <h1>Selamat Datang</h1>
      <Tombol />
      <Tombol />
      <Tombol />
    </div>
  );
}

Lihat? Halaman memanggil Tombol tiga kali. Hasilnya: 3 tombol muncul di halaman. Ini kayak kamu pakai balok LEGO yang sama berulang kali.

💡Info

Bayangin component itu resep:

  • <Tombol /> = resep bikin tombol
  • <Navbar /> = resep bikin navigation bar
  • <Halaman /> = resep bikin halaman yang pakai resep Tombol dan Navbar di dalamnya

Kamu nggak perlu tulis ulang kode tombol setiap kali butuh tombol. Cukup panggil <Tombol />.


JSX — HTML di Dalam JavaScript

Markup yang kamu lihat di atas (<button>, <div>, dll) bukan HTML biasa. Itu namanya JSX (JavaScript XML).

JSX = cara menulis "HTML" di dalam file JavaScript.

jsx
// Ini JSX, bukan HTML!
function Kartu() {
  return (
    <div className="kartu">
      <h2>Judul</h2>
      <p>Deskripsi</p>
    </div>
  );
}

Perbedaan JSX vs HTML

HTMLJSXKenapa?
class="..."className="..."class sudah jadi keyword di JavaScript
<br><br />JSX wajib tutup semua tag
<img><img />Sama — wajib self-closing
for="..."htmlFor="..."for sudah jadi keyword di JavaScript

Kenapa Pakai JSX?

Karena UI dan logika itu saling terkait. Daripada pisah HTML di satu file dan JS di file lain, React gabungin keduanya di satu tempat. Jadi kamu bisa lihat "tampilan + perilaku" component dalam satu pandangan.


Menampilkan Data dengan Curly Braces {}

Di JSX, kamu bisa "nyisipin" JavaScript pakai kurung kurawal {}:

jsx
function ProfilUser() {
  const nama = "Yazid Akbar";
  const umur = 25;
  const foto = "https://example.com/foto.jpg";

  return (
    <div>
      <img src={foto} alt={nama} />
      <h1>{nama}</h1>
      <p>Umur: {umur} tahun</p>
      <p>Tahun lahir: {2024 - umur}</p>
    </div>
  );
}

Apa aja yang bisa masuk {}?

  • Variabel: {nama}
  • Ekspresi: {2024 - umur}
  • Pemanggilan fungsi: {nama.toUpperCase()}
  • Ternary: {umur >= 17 ? "Dewasa" : "Anak-anak"}
💡Info

Bayangin kamu bikin template surat:

Kepada Yth. , kami informasikan bahwa saldo Anda sebesar ...

Kurung kurawal di JSX fungsinya sama — tempat "lubang" yang diisi data dinamis.


Conditional Rendering — Tampilkan Sesuai Kondisi

Kadang kamu mau tampilkan sesuatu hanya kalau kondisi tertentu terpenuhi.

Cara 1: if/else biasa

jsx
function Salam({ sudahLogin }) {
  if (sudahLogin) {
    return <h1>Selamat datang kembali!</h1>;
  }
  return <h1>Silakan login dulu</h1>;
}

Cara 2: Ternary operator (lebih ringkas)

jsx
function Salam({ sudahLogin }) {
  return (
    <h1>{sudahLogin ? "Selamat datang kembali!" : "Silakan login dulu"}</h1>
  );
}

Cara 3: && (tampilkan kalau true, sembunyikan kalau false)

jsx
function Notifikasi({ jumlahPesan }) {
  return (
    <div>
      <h1>Dashboard</h1>
      {jumlahPesan > 0 && <p>Kamu punya {jumlahPesan} pesan baru!</p>}
    </div>
  );
}

Kalau jumlahPesan = 0, paragraf nggak muncul. Kalau > 0, muncul.

⚠️Perhatian
jsx
// ❌ BUG! Kalau jumlah = 0, akan render angka "0" di layar
{jumlah && <p>Ada {jumlah} item</p>}

// ✅ BENAR — pakai perbandingan eksplisit
{jumlah > 0 && <p>Ada {jumlah} item</p>}

Kenapa? Karena 0 && <p>...</p> hasilnya 0 (falsy tapi bukan false), dan React tetap render angka 0.


Rendering List — Tampilkan Data Array

Kalau kamu punya array data, gunakan .map() untuk render jadi list:

jsx
function DaftarBuah() {
  const buah = ["Apel", "Mangga", "Jeruk", "Durian"];

  return (
    <ul>
      {buah.map((item, index) => (
        <li key={index}>{item}</li>
      ))}
    </ul>
  );
}

Kenapa Harus Ada key?

key itu "KTP" setiap item di list. React pakai key untuk tahu item mana yang berubah, ditambah, atau dihapus.

jsx
// ✅ BAGUS — pakai ID unik
{produk.map((p) => (
  <li key={p.id}>{p.nama}</li>
))}

// ⚠️ KURANG BAGUS — pakai index (bisa bug kalau urutan berubah)
{produk.map((p, index) => (
  <li key={index}>{p.nama}</li>
))}

Contoh Lebih Lengkap: Daftar Kontak

jsx
function DaftarKontak() {
  const kontak = [
    { id: 1, nama: "Budi", telp: "0812-1234-5678" },
    { id: 2, nama: "Ani", telp: "0813-9876-5432" },
    { id: 3, nama: "Citra", telp: "0856-1111-2222" },
  ];

  return (
    <div>
      <h2>Kontak Saya</h2>
      {kontak.map((orang) => (
        <div key={orang.id} style={{ marginBottom: "10px" }}>
          <strong>{orang.nama}</strong>
          <p>{orang.telp}</p>
        </div>
      ))}
    </div>
  );
}

Merespons Event — Bikin Tombol Interaktif

Component bisa merespons aksi user (klik, ketik, hover, dll) lewat event handler:

jsx
function TombolAlert() {
  function handleKlik() {
    alert("Tombol diklik!");
  }

  return (
    <button onClick={handleKlik}>
      Klik Saya
    </button>
  );
}

Aturan Penting

jsx
// ✅ BENAR — pass fungsi (tanpa tanda kurung)
<button onClick={handleKlik}>

// ❌ SALAH — ini LANGSUNG dipanggil saat render!
<button onClick={handleKlik()}>

Kenapa? handleKlik() dengan kurung artinya "panggil sekarang". Tanpa kurung artinya "simpan dulu, panggil nanti kalau diklik".

Event Handler Inline

Kalau logikanya pendek, bisa langsung tulis inline:

jsx
<button onClick={() => alert("Halo!")}>
  Sapa
</button>

Contoh: Tombol Counter

jsx
function Counter() {
  let angka = 0;

  function tambah() {
    angka = angka + 1;
    console.log(angka); // Angka bertambah di console...
    // ...tapi tampilan TIDAK berubah! 😱
  }

  return (
    <div>
      <p>Angka: {angka}</p>
      <button onClick={tambah}>+1</button>
    </div>
  );
}

Lho kok tampilannya nggak berubah? Karena React nggak tahu kalau angka berubah. Kita butuh State!


State — Memori Component

State adalah data yang "diingat" oleh component dan bisa berubah seiring waktu. Kalau state berubah, React otomatis re-render (gambar ulang) component-nya.

jsx
import { useState } from 'react';

function Counter() {
  const [angka, setAngka] = useState(0);

  function tambah() {
    setAngka(angka + 1); // Update state → React re-render
  }

  return (
    <div>
      <p>Angka: {angka}</p>
      <button onClick={tambah}>+1</button>
    </div>
  );
}

Cara Kerja useState

jsx
const [nilaiSekarang, fungsiUntukUpdate] = useState(nilaiAwal);
  • nilaiSekarang — nilai state saat ini
  • fungsiUntukUpdate — fungsi untuk mengubah state
  • nilaiAwal — nilai pertama kali (hanya dipakai saat render pertama)
💡Info

Bayangin papan skor di pertandingan basket:

  • State = angka di papan skor (bisa berubah)
  • setState = operator yang pencet tombol untuk ganti angka
  • Re-render = papan skor refresh menampilkan angka baru

Kalau kamu cuma teriak "SKOR BERUBAH!" tanpa pencet tombol (tanpa setState), papan skor tetap nunjukin angka lama.

Setiap Component Punya State Sendiri

jsx
function App() {
  return (
    <div>
      <Counter /> {/* Punya state sendiri: 0, 1, 2, ... */}
      <Counter /> {/* Punya state sendiri: 0, 1, 2, ... */}
    </div>
  );
}

Dua <Counter /> di atas independen. Klik satu nggak ngaruh ke yang lain. Masing-masing punya "memori" sendiri.


Hooks — Fungsi Spesial React

useState itu salah satu Hook. Hook adalah fungsi spesial yang dimulai dengan kata use.

Aturan Hook (WAJIB diikuti!)

  1. Hanya panggil di level teratas component — jangan di dalam if, loop, atau fungsi nested
  2. Hanya panggil di dalam component React — jangan di fungsi biasa
jsx
// ❌ SALAH
function Counter() {
  if (true) {
    const [angka, setAngka] = useState(0); // Hook di dalam if!
  }
}

// ✅ BENAR
function Counter() {
  const [angka, setAngka] = useState(0); // Hook di level teratas
  // ...
}

Kenapa Ada Aturan Ini?

React melacak Hook berdasarkan urutan pemanggilan. Kalau kamu taruh Hook di dalam if, urutannya bisa berubah-ubah tiap render — React jadi bingung Hook mana yang mana.


Berbagi Data Antar Component (Lifting State Up)

Kadang kamu mau 2 component sinkron — kalau satu berubah, yang lain ikut berubah.

Masalah: State Terpisah

jsx
function App() {
  return (
    <div>
      <Counter /> {/* angka: 3 */}
      <Counter /> {/* angka: 0 — nggak ikut berubah */}
    </div>
  );
}

Solusi: Angkat State ke Parent

jsx
import { useState } from 'react';

function App() {
  const [angka, setAngka] = useState(0);

  return (
    <div>
      <h1>Angka: {angka}</h1>
      <Tombol onClick={() => setAngka(angka + 1)} label="+1" />
      <Tombol onClick={() => setAngka(angka - 1)} label="-1" />
    </div>
  );
}

function Tombol({ onClick, label }) {
  return <button onClick={onClick}>{label}</button>;
}

Sekarang kedua tombol mengontrol satu state yang sama di parent. Ini namanya "Lifting State Up" — angkat state ke component terdekat yang membutuhkannya.

💡Info
  • Tanpa lifting state: Setiap orang punya TV sendiri. Ganti channel di TV kamu nggak ngaruh ke TV orang lain.
  • Dengan lifting state: Satu TV, banyak remote. Siapapun yang pencet remote, TV yang sama berubah.

Props — Kirim Data ke Component Anak

Props (properties) adalah cara mengirim data dari parent ke child component.

jsx
function KartuProduk({ nama, harga, stok }) {
  return (
    <div className="kartu">
      <h3>{nama}</h3>
      <p>Rp {harga.toLocaleString()}</p>
      <p>{stok > 0 ? `Stok: ${stok}` : "Habis"}</p>
    </div>
  );
}

function Toko() {
  return (
    <div>
      <KartuProduk nama="Laptop" harga={15000000} stok={5} />
      <KartuProduk nama="Mouse" harga={250000} stok={0} />
      <KartuProduk nama="Keyboard" harga={500000} stok={12} />
    </div>
  );
}

Props vs State

PropsState
Dikirim dari parentDimiliki component sendiri
Read-only (nggak bisa diubah child)Bisa diubah lewat setState
Kayak argumen fungsiKayak variabel lokal yang "diingat"
💡Info
  • Props = pesan yang dikirim bos ke karyawan ("Kerjakan ini dengan data ini")
  • State = catatan pribadi karyawan ("Saya sudah selesai 3 dari 5 tugas")

Karyawan nggak bisa mengubah pesan dari bos (props immutable), tapi bisa update catatan pribadinya sendiri (state mutable).


⚠️ Jebakan Umum Pemula React

1. Lupa import useState

jsx
// ❌ Error: useState is not defined
function App() {
  const [count, setCount] = useState(0);
}

// ✅ Tambahkan import di atas
import { useState } from 'react';

2. Mutasi state langsung

jsx
// ❌ SALAH — React nggak tahu state berubah
const [items, setItems] = useState(["apel"]);
items.push("mangga"); // Mutasi langsung!

// ✅ BENAR — buat array baru
setItems([...items, "mangga"]);

3. State update nggak langsung terasa

jsx
function handleKlik() {
  setAngka(angka + 1);
  console.log(angka); // Masih angka LAMA! 😱
  // State baru berlaku di render BERIKUTNYA
}

4. Render infinite loop

jsx
// ❌ INFINITE LOOP — setState dipanggil setiap render!
function App() {
  const [x, setX] = useState(0);
  setX(x + 1); // Ini dipanggil setiap render → trigger render lagi → loop!
  return <p>{x}</p>;
}

// ✅ BENAR — setState hanya di event handler atau useEffect
function App() {
  const [x, setX] = useState(0);
  return <button onClick={() => setX(x + 1)}>{x}</button>;
}

5. Component name lowercase

jsx
// ❌ React anggap ini HTML tag (yang nggak ada)
function kartuProduk() { ... }
<kartuProduk />

// ✅ Huruf kapital
function KartuProduk() { ... }
<KartuProduk />

🏋️ Challenge

Challenge 1: Kartu Profil

Buat component KartuProfil yang menerima props nama, pekerjaan, dan kota. Tampilkan dalam format:

┌─────────────────────┐ │ Budi Santoso │ │ Software Engineer │ │ 📍 Jakarta │ └─────────────────────┘

Panggil component ini 3 kali dengan data berbeda.

💡 Hint

Gunakan destructuring di parameter: function KartuProfil({ nama, pekerjaan, kota })

✅ Solusi
jsx
function KartuProfil({ nama, pekerjaan, kota }) {
  return (
    <div style={{ border: "1px solid #ccc", padding: "16px", borderRadius: "8px", marginBottom: "12px" }}>
      <h3>{nama}</h3>
      <p>{pekerjaan}</p>
      <p>📍 {kota}</p>
    </div>
  );
}

function App() {
  return (
    <div>
      <KartuProfil nama="Budi Santoso" pekerjaan="Software Engineer" kota="Jakarta" />
      <KartuProfil nama="Ani Wijaya" pekerjaan="UI Designer" kota="Bandung" />
      <KartuProfil nama="Citra Dewi" pekerjaan="Data Analyst" kota="Surabaya" />
    </div>
  );
}

Challenge 2: Toggle Tampilkan/Sembunyikan

Buat component dengan tombol yang toggle teks. Kalau diklik, teks muncul. Diklik lagi, teks hilang.

  • State: tampil (true/false)
  • Tombol text: "Tampilkan" kalau tersembunyi, "Sembunyikan" kalau terlihat
  • Teks yang di-toggle: "Ini adalah teks rahasia! 🤫"
💡 Hint

Gunakan useState(false) dan toggle dengan setTampil(!tampil). Pakai && untuk conditional render.

✅ Solusi
jsx
import { useState } from 'react';

function RahasiaTeks() {
  const [tampil, setTampil] = useState(false);

  return (
    <div>
      <button onClick={() => setTampil(!tampil)}>
        {tampil ? "Sembunyikan" : "Tampilkan"}
      </button>
      {tampil && <p>Ini adalah teks rahasia! 🤫</p>}
    </div>
  );
}

Challenge 3: Daftar Todo Sederhana

Buat component todo list:

  • Input untuk ketik todo baru
  • Tombol "Tambah" untuk menambahkan ke list
  • Tampilkan semua todo dalam <ul>

Hint: Butuh 2 state — satu untuk input text, satu untuk array todo.

💡 Hint
jsx
const [input, setInput] = useState("");
const [todos, setTodos] = useState([]);

Untuk tambah: setTodos([...todos, input]) lalu setInput("")

✅ Solusi
jsx
import { useState } from 'react';

function TodoList() {
  const [input, setInput] = useState("");
  const [todos, setTodos] = useState([]);

  function handleTambah() {
    if (input.trim() === "") return; // Jangan tambah kalau kosong
    setTodos([...todos, input]);
    setInput(""); // Reset input
  }

  return (
    <div>
      <h2>Todo List</h2>
      <input
        value={input}
        onChange={(e) => setInput(e.target.value)}
        placeholder="Tulis todo..."
      />
      <button onClick={handleTambah}>Tambah</button>

      <ul>
        {todos.map((todo, index) => (
          <li key={index}>{todo}</li>
        ))}
      </ul>

      <p>Total: {todos.length} todo</p>
    </div>
  );
}

Challenge 4: Counter dengan Min/Max

Buat counter yang:

  • Punya tombol +1 dan -1
  • Tidak bisa kurang dari 0 (minimum)
  • Tidak bisa lebih dari 10 (maximum)
  • Tampilkan warning kalau sudah di batas
✅ Solusi
jsx
import { useState } from 'react';

function CounterMinMax() {
  const [angka, setAngka] = useState(0);
  const MIN = 0;
  const MAX = 10;

  function tambah() {
    if (angka < MAX) setAngka(angka + 1);
  }

  function kurang() {
    if (angka > MIN) setAngka(angka - 1);
  }

  return (
    <div>
      <h2>Counter: {angka}</h2>
      <button onClick={kurang} disabled={angka <= MIN}>-1</button>
      <button onClick={tambah} disabled={angka >= MAX}>+1</button>
      {angka >= MAX && <p style={{ color: "red" }}>Sudah maksimum!</p>}
      {angka <= MIN && <p style={{ color: "red" }}>Sudah minimum!</p>}
    </div>
  );
}

Sudah paham materi ini?

Tandai sebagai selesai untuk melacak progress-mu.