State dengan useState — React

Bayangin tombol Like di Instagram. Di-klik — angka likenya naik 1, ikon hati berubah merah, animasi heartbeat jalan. Klik lagi — semua kebalik. Komponen yang…

State adalah data yang diingat komponen di antara render, misalnya angka di counter atau status aktif sebuah tombol. Kamu menyimpannya dengan hook useState (hook adalah fungsi khusus React yang namanya diawali use). Begitu state diganti lewat setter-nya, React render ulang komponen itu: memanggil function komponennya lagi dan memperbarui halaman sesuai hasilnya. Bayangin papan skor futsal. Angkanya dipegang operator, bukan pemain. Pemain cuma bisa bilang "skornya jadi 1", lalu operator memasang angka baru dan semua orang membaca papan yang baru. Di React, operatornya React, dan papan yang sedang terpasang adalah render yang sedang berjalan.

🧪 Tebakan cepat: count mulai dari 0. Satu klik menjalankan setCount(count + 1) tiga kali berturut-turut. Angkanya jadi 1 atau 3? Tebak dulu, jawabannya ada di bagian "Tiap render memegang nilainya sendiri".

Kenapa variabel biasa gak cukup

function Counter() {
  let count = 0

  return (
    <button onClick={() => { count = count + 1 }}>
      Diklik {count} kali
    </button>
  )
}

Diklik berapa kali pun, tombolnya tetap "Diklik 0 kali". Ada dua alasan:

State menyelesaikan dua-duanya: nilainya disimpan React di luar function, dan setter-nya meminta render ulang.

useState: nilai dan setter

import { useState } from "react"

function Counter() {
  const [count, setCount] = useState(0)

  return (
    <div>
      <span id="count">{count}</span>
      <button id="increment" onClick={() => setCount(count + 1)}>+1</button>
    </div>
  )
}
Kejadian count di render ini Yang diminta Tampil
Render pertama 0 0
Klik +1 0 setCount(0 + 1)
Render ke-2 1 1
Klik +1 1 setCount(1 + 1)
Render ke-3 2 2

Saklar: state true atau false

State gak harus angka. Untuk saklar, simpan boolean dan balik nilainya:

function App() {
  const [active, setActive] = useState(true)

  return (
    <div>
      <p id="status">{active ? "Aktif" : "Nonaktif"}</p>
      <button id="toggle" onClick={() => setActive(!active)}>Toggle</button>
    </div>
  )
}

Tiap render memegang nilainya sendiri

Di dalam satu render, count itu konstanta. setCount gak mengubah count yang sedang dipegang handler, dia menjadwalkan render baru dengan nilai baru.

function handleClick() {
  setCount(count + 1) // count di render ini 0: minta "jadikan 1"
  setCount(count + 1) // count masih 0: minta "jadikan 1" lagi
  setCount(count + 1) // sama: "jadikan 1"
  console.log(count)  // 0, nilai milik render ini
}

Satu klik dari 0 hasilnya 1, bukan 3. Itu jawaban tebakannya. Sama kayak bilang ke operator "jadikan 1" tiga kali: papannya tetap 1. console.log(count) mencetak 0, karena handler ini milik render yang count-nya 0. Nilai 1 baru ada di render berikutnya.

Kalau mau "tambah 1" tiga kali, kirim fungsi, bukan nilai:

function handleClick() {
  setCount(c => c + 1) // antrean: 0 + 1 = 1
  setCount(c => c + 1) // antrean: 1 + 1 = 2
  setCount(c => c + 1) // antrean: 2 + 1 = 3
}

Object dan array: bikin yang baru

React membandingkan state lama dan baru. Kalau yang dikirim object yang sama persis, React menganggapnya gak berubah dan layar gak diperbarui.

const [user, setUser] = useState({ name: "Budi", age: 17 })

user.age = 18                  // salah: mengubah object lama
setUser(user)                  // object yang sama, layar gak berubah

setUser({ ...user, age: 18 })  // benar: object baru, isinya disalin lalu age diganti
setItems([...items, "baru"])   // array baru dengan satu isi tambahan

⚠️ Jebakan yang sering ketemu

TL;DR: const [count, setCount] = useState(0) menyimpan state dengan nilai awal 0. count adalah nilai di render ini, dan gak berubah selama render itu. setCount(...) menjadwalkan render baru dengan nilai baru, jadi console.log(count) sesudahnya masih mencetak nilai lama. setCount(count + 1) tiga kali dalam satu klik cuma menambah 1, setCount(c => c + 1) tiga kali menambah 3. Untuk saklar, simpan boolean dan balik dengan setActive(!active). Object dan array diganti dengan yang baru ({ ...user, age: 18 }), jangan diubah langsung. Hook selalu dipanggil di level paling luar komponen, bukan di dalam if atau loop.

Yang akan kamu pelajari