useRef — React

useState re-render component tiap state berubah — itu fitur, bukan bug. Tapi kadang kamu butuh simpan nilai yang persist antar render TANPA trigger re-render: p

useState re-render component tiap state berubah — itu fitur, bukan bug. Tapi kadang kamu butuh simpan nilai yang persist antar render TANPA trigger re-render: pegangan ke DOM element (buat focus input), ID interval (buat clear), nilai yang di-update sering tapi gak perlu di-display. Itu jobs useRef. Plus, ini juga cara satu-satunya akses DOM element langsung dari React — escape hatch ke imperative world saat declarative React gak cukup.

🤔 Bukan pengganti useState. useState = nilai display di UI (state berubah → re-render). useRef = nilai PRESISTEN tapi UI gak peduli (focus DOM, timer ID). Salah pilih = bug. Mau counter di tampilkan di layar? useState. Mau counter buat tracking jumlah klik tanpa display? Bisa useRef. Mau pegang DOM input buat panggil .focus()? useRef.

Akses DOM Element — Use Case Utama

function App() {
  const inputRef = useRef(null)

  const focusInput = () => {
    inputRef.current.focus()
  }

  return (
    <div>
      <input ref={inputRef} />
      <button onClick={focusInput}>Focus Input</button>
    </div>
  )
}

ref={inputRef} = pasang ref ke element. React isi .current dengan DOM node setelah render.

Simpan Nilai Tanpa Re-render

function StopWatch() {
  const [time, setTime] = useState(0)
  const intervalRef = useRef(null)  // simpan ID interval

  const start = () => {
    intervalRef.current = setInterval(() => {
      setTime(t => t + 1)
    }, 1000)
  }

  const stop = () => clearInterval(intervalRef.current)

  return (
    <div>
      <p>{time}s</p>
      <button onClick={start}>Start</button>
      <button onClick={stop}>Stop</button>
    </div>
  )
}

time di-display → useState. intervalRef.current cuma buat track ID interval (gak displayed) → useRef.

Kunci Properties

useState useRef
Trigger re-render saat berubah TIDAK trigger re-render
Snapshot per render Selalu nilai TERKINI
Akses via destructure [val, setVal] Akses via .current
Untuk data yang DI-DISPLAY Untuk data internal / DOM ref

Akses DOM Setelah Render — Pakai useEffect

function ChatBox({ messages }) {
  const bottomRef = useRef(null)

  useEffect(() => {
    bottomRef.current?.scrollIntoView({ behavior: "smooth" })
  }, [messages])  // scroll ke bawah tiap message baru

  return (
    <div className="chat">
      {messages.map(m => <Message key={m.id} {...m} />)}
      <div ref={bottomRef} />
    </div>
  )
}

🎭 Analogi sehari-hari

useRef itu kayak kantong kecil rahasia di tas. useState = label tas yang kelihatan dari luar (orang liat tas kuning, pas kamu ganti tas merah, semua liat). useRef = isi kantong rahasia di dalam tas — bisa berubah berkali-kali, tapi orang luar gak ngeh sampai kamu sengaja ngeluarinnya. Pas kamu butuh nyimpen sesuatu yang fungsional tapi gak perlu "diumumkan ulang" tiap kali berubah (KTP, kunci, ID interval), useRef tempatnya. Plus, useRef juga kayak tag GPS yang nempel di paket — kamu bisa "tunjuk" ke object yang udah ada (DOM element) tanpa nyimpen object-nya sendiri.

⚠️ Jebakan yang sering ditemui

🎯 useRef vs useState — pilih mana?

  • Nilai DI-DISPLAY di UIuseState (counter, input value, list items)
  • Pegangan ke DOM elementuseRef (focus, scrollIntoView, measure)
  • Timer ID, interval ID, subscription IDuseRef (gak displayed, gak butuh re-render)
  • Track previous value (compare prev vs current state) → useRef di useEffect
  • Cache hasil komputasiuseMemo (lebih semantik) atau useRef
  • Mutable instance seperti class instance → useRef

Aturan praktis: butuh re-render saat berubah? useState. Cuma butuh persist + mutate? useRef.

TL;DR: useRef(initial) = nilai persist antar render TANPA trigger re-render. Akses via .current. Use case utama: (1) pegangan ke DOM element (<input ref={ref}> lalu ref.current.focus()), (2) simpan timer ID/listener ID, (3) track previous value. Beda dari useState: gak re-render saat ubah .current. DOM ref di-set SETELAH render — akses di useEffect/event handler, BUKAN di body component.

Yang akan kamu pelajari