Friday, April 17, 2026
No menu items!
HomeWeb DevelopmentBelajar ReactMeracik Custom Hooks: Logika Reusable di React

Meracik Custom Hooks: Logika Reusable di React

Di balik tampilan antarmuka React yang rapi dan interaktif, ada satu hal yang sering kali tersembunyi: logika yang berulang-ulang. Ambil contoh sederhana-mengelola status loading, menangani permintaan API, atau memantau ukuran jendela browser. Kode yang sama bisa muncul di banyak komponen, hanya dengan sedikit variasi. Lama-kelamaan, aplikasi terasa penuh duplikasi, sulit dirawat, dan makin kompleks setiap kali fitur baru ditambahkan.

Di sinilah custom hooks berperan. Dengan meracik custom hooks, kita dapat “mengemas” logika yang berulang menjadi fungsi-fungsi kecil yang rapi, dapat dipakai ulang, dan mudah diuji. Alih-alih menyalin potongan useEffect dan useState dari satu komponen ke komponen lain, kita cukup memanggil satu hook khusus yang sudah mengurus semuanya di balik layar.

Artikel ini akan membahas bagaimana merancang custom hooks di React secara sistematis: mulai dari mengenali pola logika yang layak diekstrak, menyusun struktur hook yang bersih, hingga memastikan hook tersebut benar-benar reusable dan tidak bergantung pada konteks komponen tertentu. Dengan begitu, alur logika aplikasi menjadi lebih jelas, komponen lebih ringan, dan pengembangan menjadi jauh lebih terukur.

Memahami Kapan Perlu Custom Hook dan Kapan Cukup Komponen Biasa

Bayangkan setiap kali butuh fetch data, kamu selalu copy-paste efek, state loading, dan error ke banyak komponen. Di titik ini, sinyalnya sudah jelas: waktunya ekstrak ke custom hook. Aturannya sederhana: kalau suatu logika UI non-trivial muncul lebih dari sekali, terutama yang menyentuh state, efek samping, atau interaksi kompleks (misalnya scroll listener, resize window, atau debounced search), biasanya ia lebih “betah” tinggal di hook daripada di komponen. Komponen jadi fokus pada tampilan, sedangkan hook fokus pada perilaku. Untuk pola seperti ini, kamu bakal sering nemu hook seperti:

  • useFetchProduct – nangani fetch data produk, termasuk caching dan error.
  • useFormHandler – urus value, error, dan submit form yang mirip-mirip.
  • useModal – buka/tutup modal dengan pola yang konsisten di seluruh aplikasi.
Kondisi Pakai Custom Hook Cukup Komponen
Logika dipakai di banyak tempat Ya Tidak
Hanya butuh sekali di satu halaman Mungkin berlebihan Ya
Lebih banyak urusan tampilan Tidak wajib Ya

Di sisi lain, kalau logika kamu sebenarnya cuma “bumbu kecil” yang spesifik banget ke satu tampilan – misalnya toggle sederhana di satu card, atau state untuk buka/tutup dropdown unik di satu halaman – memaksa semuanya jadi hook bisa bikin kode terpecah-pecah dan susah diikuti. Kadang, komponen biasa yang sedikit “pintar” itu lebih sehat ketimbang membabi buta bikin file useSomething.js untuk tiap hal. Pertimbangkan:

  • Apakah logika ini mungkin dipakai ulang dalam waktu dekat?
  • Apakah memindahkannya ke hook bikin alur baca kode jadi lebih jelas, bukan malah lebih abstrak?
  • Apakah tim kamu bisa langsung paham maksud hook itu hanya dari namanya?

Kalau jawabannya banyak yang “tidak”, biarkan dia tetap sebagai logika di dalam komponen. Custom hook itu alat, bukan kewajiban; gunakannya saat ia benar-benar bikin struktur kode lebih ringkas, konsisten, dan gampang dipahami, bukan sekadar demi terlihat “lebih React”.

Mendesain API Custom Hook yang Elegan dan Mudah Ditebak

API hook yang enak dipakai itu biasanya punya tiga ciri: nama yang jelas, parameter yang seperlunya, dan nilai balik yang gampang ditebak. Di React, pola penamaan seperti useSomething bukan cuma formalitas, tapi semacam janji: “ini hook, dan kamu bisa memperlakukan dia seperti hook lain pada umumnya.” Misalnya, alih-alih bikin useData() yang super generik dan membingungkan, lebih baik useUserProfile() atau useCart() dengan kontrak yang spesifik. Supaya makin rapi, usahakan API-nya konsisten antar-hook: kalau satu hook balikin { data, isLoading, error }, hook lain yang juga fetch data sebaiknya pakai pola yang mirip. Pola ini bikin orang lain (atau diri kita sendiri di masa depan) bisa “nebak” cara pakainya tanpa harus baca file dari atas sampai bawah.

  • Gunakan nama fungsi yang deskriptif dan konsisten
  • Bedakan props konfigurasi dan state hasil olahan dengan jelas
  • Utamakan satu tanggung jawab utama per hook
  • Pastikan struktur return hook stabil dan jarang berubah
Pola Nama Perilaku yang Diharapkan
useXxxState Kelola state + setter
useXxxQuery Fetch data + status loading/error
useXxxEffect Side effect terkontrol

Supaya lebih eksplisit dan mudah ditebak, banyak developer suka mengembalikan object daripada array, karena urutan properti jadi nggak penting dan pemanggil bisa pakai destructuring dengan nama yang jelas. Contohnya, bayangkan sebuah hook untuk menyimpan form dengan status async yang rapi dan “kebaca maksudnya”:

function useSaveProfile(options?: { autoSave?: boolean }) {
  const [isSaving, setIsSaving] = useState(false);
  const [error, setError] = useState(null);

  const save = useCallback(async (payload: ProfilePayload) => {
    setIsSaving(true);
    setError(null);
    try {
      await api.saveProfile(payload);
    } catch (err) {
      setError(err as Error);
    } finally {
      setIsSaving(false);
    }
  }, []);

  return {
    save,
    isSaving,
    error,
    canRetry: !!error && !isSaving,
  };
}

  • Nama hook jelas: fokus ke penyimpanan profil, bukan “segala hal tentang user”
  • Parameter opsional dikemas dalam satu object options
  • Nilai balik punya pola yang gampang dihafal: action + status + helper flag

Menyusun Struktur File dan Penamaan Custom Hook untuk Skala Aplikasi Besar

Di proyek kecil, kita bisa saja menaruh semua custom hook di satu file dan tetap aman. Tapi begitu aplikasi mulai tumbuh, pendekatan ini cepat bikin pusing. Cara yang lebih sehat adalah mengelompokkan hook berdasarkan domain atau fitur, bukan hanya jenis teknisnya. Misalnya, letakkan hook yang berkaitan dengan autentikasi di folder auth, hook untuk keranjang belanja di folder cart, dan seterusnya. Biasanya pola yang rapi akan terlihat seperti ini:

  • Folder per fitur (misalnya features/auth, features/cart) yang berisi komponen + hook + service terkait.
  • Hook generik (misalnya useDebounce, useToggle) disimpan di folder terpisah seperti shared/hooks.
  • File terpisah untuk tiap hook agar mudah di-scan di code review dan gampang di-refactor.
Jenis Hook Contoh Nama Lokasi Disarankan
Domain-spesifik useAuthUser src/features/auth/hooks
UI behavior useModal src/shared/hooks
Networking useFetchOrders src/features/orders/hooks

Penamaan juga krusial, terutama di skala besar di mana ratusan file berlomba cari perhatian di sidebar editor. Aturan dasarnya: selalu awali dengan use, lalu tambahkan kata kerja + konteks yang jelas. Hindari nama generik seperti useData atau useLogic yang tidak memberi petunjuk apa pun. Lebih baik sedikit panjang tapi deskriptif, misalnya useSyncCartWithServer ketimbang useCartSync yang masih agak abu-abu. Untuk memudahkan navigasi, banyak tim juga membuat satu index.ts per folder hook untuk melakukan re-export, supaya import tetap ringkas tanpa mengorbankan struktur:

“`tsx
// src/features/auth/hooks/useAuthUser.ts
export function useAuthUser() {
// …
}

// src/features/auth/hooks/index.ts
export * from “./useAuthUser”;
export * from “./useAuthGuard”;
“`

Menguji dan Mendokumentasikan Custom Hook agar Konsisten dan Mudah Dipakai Tim

Supaya hook buatanmu nggak berubah jadi “kotak hitam” yang bikin satu tim bingung, pastikan dia punya dua hal: uji yang jelas dan dokumen yang ramah manusia. Untuk pengujian, fokus ke perilaku, bukan implementasi. Misalnya, kalau kamu bikin useFetch, uji bagaimana state berubah saat request mulai, sukses, atau gagal. Gunakan testing library seperti React Testing Library dan Jest untuk menyimulasikan render, update state, dan efek. Sertakan juga beberapa edge case: error network, data kosong, atau pemanggilan berulang. Yang penting: hasil akhirnya bisa diprediksi, dan kalau ada bug, tim tahu harus mulai nyari dari mana.

Setelah yakin hook-nya stabil, bungkus dengan dokumentasi yang enak dibaca: jelaskan apa masalah yang diselesaikan, kapan sebaiknya dipakai, dan contoh penggunaan minimal namun nyata. Tambahkan catatan kecil soal batasan atau caveat-misalnya butuh provider tertentu, atau hanya aman dipanggil di client. Untuk memudahkan tim, kamu bisa bikin pola dokumentasi standar seperti di bawah ini:

Bagian Isi Singkat
Tujuan Menjelaskan masalah yang dipecahkan hook
API Parameter masuk & nilai kembali
Contoh Potongan kode simpel dan bisa dipakai ulang
Catatan Limitasi, dependency, dan best practice
  • Selalu sertakan contoh kode lengkap, dari import sampai penggunaan.
  • Gunakan nama variabel yang deskriptif, bukan sekadar data atau res.
  • Sinkronkan dokumen dan kode tiap kali ada perubahan API.

// contoh struktur dokumentasi + implementasi singkat

// useToggle.ts
import { useState, useCallback } from "react";

/**
 * Tujuan: Mengelola state boolean sederhana (on/off, show/hide, dll).
 * API:
 *   - initialValue?: boolean (default: false)
 * Return:
 *   - value: boolean
 *   - toggle: () => void
 *   - setOn: () => void
 *   - setOff: () => void
 */
export function useToggle(initialValue: boolean = false) {
  const [value, setValue] = useState(initialValue);

  const toggle = useCallback(() => setValue((prev) => !prev), []);
  const setOn = useCallback(() => setValue(true), []);
  const setOff = useCallback(() => setValue(false), []);

  return { value, toggle, setOn, setOff };
}

// useToggle.test.tsx
import { renderHook, act } from "@testing-library/react";
import { useToggle } from "./useToggle";

test("harus menggunakan nilai awal yang diberikan", () => {
  const { result } = renderHook(() => useToggle(true));
  expect(result.current.value).toBe(true);
});

test("toggle harus membalik nilai", () => {
  const { result } = renderHook(() => useToggle(false));

  act(() => {
    result.current.toggle();
  });

  expect(result.current.value).toBe(true);
});

test("setOn dan setOff harus mengatur nilai dengan eksplisit", () => {
  const { result } = renderHook(() => useToggle(false));

  act(() => {
    result.current.setOn();
  });
  expect(result.current.value).toBe(true);

  act(() => {
    result.current.setOff();
  });
  expect(result.current.value).toBe(false);
});

Future Outlook

Pada akhirnya, meracik custom hooks bukan sekadar trik teknis di React-ini adalah cara kita merapikan cara berpikir tentang logika, keteraturan, dan kolaborasi dalam sebuah aplikasi. Setiap kali Anda memindahkan sebaris logika dari komponen ke dalam sebuah hook, Anda sebenarnya sedang membangun “bahasa kecil” yang bisa dipahami ulang oleh tim, dipakai ulang oleh proyek lain, dan dikembangkan tanpa harus mengulang dari nol.

Setelah ini, Anda bisa mulai dari hal paling sederhana: ekstrak satu pola yang sering berulang, beri nama yang jujur dan deskriptif, lalu lihat bagaimana komponen Anda perlahan menjadi lebih ringkas dan mudah dibaca. Dari sana, biarkan kebiasaan meracik custom hooks tumbuh alami-bukan karena “trend React”, tapi karena ia benar-benar membuat hidup Anda sebagai developer menjadi lebih tertata.

Pada dunia yang kodenya berubah cepat, custom hooks adalah salah satu cara kecil untuk menjaga agar logika tetap konsisten, mudah dirawat, dan siap digunakan kembali kapan pun dibutuhkan. Selebihnya, terserah Anda: logika apa yang ingin Anda sulap menjadi hook pertama berikutnya?

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisment -
Google search engine

Most Popular

Recent Comments