Custom Hooks — React

Bayangin 5 komponen di app kamu masing-masing pake pattern: useState buat data, useState buat loading, useEffect buat fetch — copy-paste kode yang sama 5x…

Custom hook adalah function biasa yang namanya diawali use dan memanggil hook lain di dalamnya, misalnya useState. Dengan custom hook, logika yang memegang state (state plus cara mengubahnya) cukup ditulis sekali, lalu dipakai di banyak komponen. Mirip satu resep rendang yang dipakai dua dapur: resepnya sama, tapi tiap dapur memasak di pancinya sendiri. Kalau dapur A menambah garam, panci dapur B gak ikut asin.

🧪 Tebakan cepat: lampu Teras dan lampu Dapur sama-sama memanggil useToggle(true). Kamu klik Toggle di Teras sampai jadi OFF. Apakah Dapur ikut OFF? Tebak dulu, jawabannya ada di bagian "Tiap panggilan punya state sendiri".

Logika yang sama ditulis berulang

Dua komponen ini sama-sama butuh nilai true atau false yang bisa dibalik:

function Lamp({ name, initial }) {
  const [isOn, setIsOn] = useState(initial)
  const toggle = () => setIsOn((v) => !v)

  return (
    <div>
      <p>{name}: {isOn ? "ON" : "OFF"}</p>
      <button onClick={toggle}>Toggle</button>
    </div>
  )
}

function Spoiler() {
  const [isOpen, setIsOpen] = useState(false)
  const toggle = () => setIsOpen((v) => !v)

  return (
    <div>
      <button onClick={toggle}>{isOpen ? "Tutup" : "Lihat jawaban"}</button>
      {isOpen && <p>Jawabannya: custom hook!</p>}
    </div>
  )
}

Dua baris pertama di tiap komponen isinya sama, cuma beda nama. Ada bug di cara membaliknya? Kamu harus membetulkannya di setiap komponen yang menyalin baris itu.

Pindahkan ke custom hook

import { useState } from "react"

function useToggle(initial = false) {
  const [value, setValue] = useState(initial)
  const toggle = () => setValue((v) => !v)
  return [value, toggle]
}

function Lamp({ name, initial }) {
  const [isOn, toggle] = useToggle(initial)

  return (
    <div>
      <p>{name}: {isOn ? "ON" : "OFF"}</p>
      <button onClick={toggle}>Toggle</button>
    </div>
  )
}

function Spoiler() {
  const [isOpen, toggle] = useToggle(false)

  return (
    <div>
      <button onClick={toggle}>{isOpen ? "Tutup" : "Lihat jawaban"}</button>
      {isOpen && <p>Jawabannya: custom hook!</p>}
    </div>
  )
}

Tiap panggilan punya state sendiri

App merender <Lamp name="Teras" initial={true} />, <Lamp name="Dapur" initial={true} />, dan <Spoiler />. Lalu kamu mengklik:

Aksi Teras Dapur Spoiler
Awal ON ON tertutup
Klik Toggle di Teras OFF ON tertutup
Klik Toggle di Teras lagi ON ON tertutup
Klik Toggle di Dapur ON OFF tertutup

useToggle dipanggil tiga kali, jadi ada tiga useState yang terpisah. Dapur tetap ON waktu Teras jadi OFF. Itu jawaban tebakannya. Custom hook membagi cara kerjanya, bukan isi state-nya. Kalau dua komponen harus memegang nilai yang sama, angkat state-nya ke induk (lifting state) atau pakai Context.

Aturan custom hook

  1. Nama diawali use: useToggle, bukan toggle atau toggleHelper. Dari awalan itu React dan linter-nya (eslint-plugin-react-hooks) tahu function ini hook, lalu mengecek aturannya.
  2. Panggil hook di tingkat atas. Jangan di dalam if, loop, atau function lain di dalamnya. Aturan ini berlaku juga di dalam custom hook.
  3. Panggil hook cuma dari komponen atau custom hook lain, bukan dari function biasa.
  4. Bentuk kembaliannya bebas. Array seperti [value, toggle] enak kalau pemakainya ingin menamai sendiri. Object juga boleh:
function useToggle() {
  const [on, setOn] = useState(false)
  const toggle = () => setOn((prev) => !prev)
  return { on, toggle }
}

const { on, toggle } = useToggle() // dibaca dengan nama yang sama

🎯 Custom hook, function biasa, atau komponen?

⚠️ Jebakan yang sering ketemu

TL;DR: Custom hook adalah function berawalan use yang memanggil hook lain, misalnya useState, untuk reuse logika stateful tanpa menyalin kode. useToggle(initial = false) menyimpan satu boolean, membuat toggle yang membaliknya dengan setValue((v) => !v), dan mengembalikan [value, toggle]. Tiap pemanggilan punya state sendiri: Teras jadi OFF, Dapur tetap ON. Ikuti aturan hook: nama diawali use, dipanggil di tingkat atas, dan cuma dari komponen atau hook lain. Yang dikembalikan boleh array atau object.

Yang akan kamu pelajari