Blog by Fadil Rumasoreng

Saya menulis tentang pengalaman saya membangun aplikasi, eksperimen teknologi, dan ide-ide seputar web development. Semua ini saya bagikan atau saya tulis murni dari pengalaman yang saya dapatkan ketika mengembangkan perangkat lunak.

Memahami React Hooks dengan Cara yang Simpel dan Relevan

CNFadil Rumasoreng· 15 Oct 2025· 0
Memahami React Hooks dengan Cara yang Simpel dan Relevan

Panduan lengkap React Hooks untuk developer pemula hingga menengah. Pelajari cara kerja useState, useEffect, useMemo, dan lainnya dengan praktik terbaik modern.


Pendahuluan: Dari Class Component ke Era Hooks

Kalau kamu baru masuk ke dunia React, mungkin pernah dengar kalimat, “Sekarang semua pakai hooks aja.” Awalnya kedengarannya seperti tren, tapi begitu kamu tahu konsep dasarnya, kamu akan paham kenapa hooks mengubah cara kita membangun aplikasi React selamanya.

Dulu, sebelum 2019, React menggunakan class component untuk mengelola state dan lifecycle. Tapi masalahnya, logika jadi sulit dipisahkan, kode mudah berantakan, dan susah untuk di-reuse. Hooks datang untuk memecahkan itu semua.

React Hooks memungkinkan kita menulis komponen fungsional yang bisa punya state, efek samping, dan logika kompleks — tanpa perlu class. Sekarang, hampir semua proyek modern seperti Next.js dan Vite + React dibangun sepenuhnya dengan Hooks.

Mari kita bahas satu per satu hooks penting yang wajib kamu kuasai untuk bisa menulis React yang bersih, efisien, dan mudah dipelihara.


1. useState – Tempat Segala Cerita Dimulai

Kalau React adalah otak aplikasi, maka useState adalah ingatannya. Hook ini memungkinkan komponen “mengingat” data antara satu render ke render berikutnya.

Misalnya kamu ingin membuat counter sederhana. Dulu kamu harus membuat this.state dan this.setState(), tapi dengan hooks, semuanya lebih mudah.

"use client";
import { useState } from "react";

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

  return (
    <div className="flex flex-col items-center gap-3">
      <p className="text-lg font-medium">Count: {count}</p>
      <button
        onClick={() => setCount(count + 1)}
        className="px-4 py-2 bg-blue-600 text-white rounded-lg"
      >
        Increment
      </button>
    </div>
  );
}

Dengan satu baris useState(0), kamu sudah punya variabel reaktif. Begitu setCount() dipanggil, React otomatis me-render ulang komponen dengan nilai baru.

Kapan dipakai? Hampir di semua kasus di mana kamu butuh menyimpan data sederhana: input form, status login, toggle modal, dan sebagainya.

Best practice: hindari menyimpan data besar (seperti hasil API) di banyak useState terpisah. Gunakan satu objek state atau global state management seperti Context bila diperlukan.


2. useEffect – Tempat Semua Efek Samping Terjadi

useEffect adalah jembatan antara React dan dunia luar. Ia digunakan untuk menjalankan efek samping seperti fetching data, event listener, atau manipulasi DOM setelah render terjadi.

Bayangkan kamu ingin memanggil API ketika komponen pertama kali muncul:

"use client";
import { useEffect, useState } from "react";

export default function FetchUser() {
  const [user, setUser] = useState<any>(null);

  useEffect(() => {
    fetch("/api/user")
      .then(res => res.json())
      .then(data => setUser(data));
  }, []);

  return <div>{user ? `Hello, ${user.name}` : "Loading..."}</div>;
}

Parameter pertama useEffect adalah fungsi yang dijalankan setelah render, sedangkan parameter kedua adalah array dependencies. Jika array kosong ([]), efek hanya dijalankan sekali saat komponen pertama kali dimuat.

Kalau kamu ingin memantau perubahan nilai tertentu (misalnya query atau id), cukup masukkan ke dalam dependencies:

useEffect(() => {
  console.log("User ID berubah:", id);
}, [id]);

Best practice: selalu tulis cleanup function jika efek kamu menambahkan event listener atau interval. Ini membantu mencegah memory leak ketika komponen dihapus.


3. useMemo – Ketika Performa Mulai Penting

Di dunia nyata, tidak semua perhitungan ringan. Kadang kamu perlu memproses data berat seperti filtering, sorting, atau menghitung hasil besar. Kalau perhitungan itu dijalankan setiap kali render, aplikasi bisa melambat. Di sinilah useMemo jadi penyelamat.

Hook ini digunakan untuk memoisasi nilai agar hanya dihitung ulang jika dependensinya berubah.

"use client";
import { useState, useMemo } from "react";

export default function Fibonacci() {
  const [num, setNum] = useState(30);

  const fibonacci = (n: number): number => {
    if (n <= 1) return n;
    return fibonacci(n - 1) + fibonacci(n - 2);
  };

  const result = useMemo(() => fibonacci(num), [num]);

  return (
    <div>
      <input
        type="number"
        value={num}
        onChange={(e) => setNum(Number(e.target.value))}
        className="border rounded px-2 py-1"
      />
      <p>Fibonacci({num}) = {result}</p>
    </div>
  );
}

Dengan useMemo, fungsi fibonacci() tidak akan dieksekusi ulang setiap render, kecuali num berubah. Ini membuat UI tetap responsif meski logika di dalamnya berat.

Best practice: gunakan useMemo hanya ketika benar-benar perlu. Terlalu banyak memoization justru bisa membuat kode sulit dibaca tanpa manfaat nyata.


4. useCallback – Optimasi Fungsi Tanpa Drama

Kalau useMemo untuk nilai, maka useCallback untuk fungsi.
Di React, setiap kali komponen re-render, semua fungsi di dalamnya dibuat ulang. Masalahnya, ketika fungsi ini dikirim ke komponen anak, ia bisa memicu re-render tidak perlu.

"use client";
import { useState, useCallback } from "react";

const Child = React.memo(({ onClick }: { onClick: () => void }) => {
  console.log("Child re-rendered");
  return <button onClick={onClick}>Click me</button>;
});

export default function Parent() {
  const [count, setCount] = useState(0);

  const handleClick = useCallback(() => {
    setCount((prev) => prev + 1);
  }, []);

  return <Child onClick={handleClick} />;
}

Dengan useCallback, fungsi handleClick tidak akan dibuat ulang di setiap render, sehingga komponen Child yang di-memo tidak akan ikut re-render.

Best practice: gunakan ini hanya ketika kamu benar-benar punya komponen anak yang dioptimasi (React.memo). Jika tidak, manfaatnya kecil.


5. useRef – Menyimpan Nilai Tanpa Re-render

useRef adalah hook yang sering diremehkan tapi sangat berguna. Ia bisa digunakan untuk dua hal:
menyimpan nilai yang tidak perlu memicu re-render, dan mengakses DOM secara langsung.

Misalnya kamu ingin fokus ke input ketika tombol diklik:

"use client";
import { useRef } from "react";

export default function FocusInput() {
  const inputRef = useRef<HTMLInputElement>(null);

  const handleFocus = () => {
    inputRef.current?.focus();
  };

  return (
    <div>
      <input ref={inputRef} type="text" className="border rounded px-2 py-1" />
      <button onClick={handleFocus} className="ml-2 px-3 py-1 bg-green-600 text-white rounded">
        Focus
      </button>
    </div>
  );
}

Tidak seperti useState, perubahan pada ref.current tidak menyebabkan re-render.
Ini membuatnya ideal untuk menyimpan state non-reaktif seperti ID timer, instance library eksternal, atau posisi scroll.


6. useContext – Menghindari Prop Drilling yang Melelahkan

Ketika aplikasi semakin besar, kamu akan mulai bosan harus terus menerus mengoper props ke banyak level komponen. useContext hadir untuk menyelesaikan masalah itu.

Dengan useContext, kamu bisa membuat state global sederhana tanpa perlu library seperti Redux.

"use client";
import { createContext, useContext, useState } from "react";

const AuthContext = createContext<any>(null);

export const AuthProvider = ({ children }: { children: React.ReactNode }) => {
  const [user, setUser] = useState<any>(null);
  return <AuthContext.Provider value={{ user, setUser }}>{children}</AuthContext.Provider>;
};

export const useAuth = () => useContext(AuthContext);

Sekarang di mana pun kamu butuh data user, cukup panggil:

import { useAuth } from "./AuthContext";

export default function Dashboard() {
  const { user } = useAuth();
  return <div>Hello, {user ? user.name : "Guest"}</div>;
}

Best practice: gunakan Context untuk data global yang jarang berubah (seperti tema atau user). Jika data sering berubah, lebih baik pakai state management eksternal seperti Zustand atau Redux Toolkit.


Tabel Ringkasan

Hook

Fungsi Utama

Re-render?

Umum Digunakan Untuk

useState

Menyimpan state lokal

Ya

Counter, form, toggle

useEffect

Menjalankan efek samping

Ya

Fetch data, event listener

useMemo

Memoisasi nilai

Tidak

Perhitungan berat

useCallback

Memoisasi fungsi

Tidak

Optimasi performa anak

useRef

Menyimpan nilai non-reaktif

Tidak

Akses DOM, timer, instance

useContext

Mengelola state global

Ya

Auth, tema, bahasa


Penutup: Hooks Bukan Sekadar Fitur

Belajar React Hooks bukan hanya tentang menghafal API, tapi memahami kenapa dan kapan kamu menggunakannya.
Hooks membuat kode React lebih modular, bisa di-reuse, dan mudah dibaca.
Begitu kamu paham pola pikirnya, kamu bisa membangun komponen yang ringan, cepat, dan mudah di-debug.

Bagi developer modern, menguasai hooks seperti useState dan useEffect adalah langkah pertama menuju dunia React yang sebenarnya.


FAQ

1. Apa bedanya useMemo dan useCallback?
useMemo digunakan untuk menyimpan hasil dari perhitungan, sementara useCallback menyimpan fungsi agar tidak dibuat ulang.

2. Apakah setiap state harus pakai useState?
Tidak. Jika state digunakan lintas komponen, pertimbangkan untuk menggunakan Context atau state management global.

3. Kapan sebaiknya menggunakan useEffect?
Gunakan useEffect hanya untuk efek samping: fetching data, manipulasi DOM, atau event listener. Hindari menaruh logika utama render di dalamnya.

4. Apakah useRef bisa menggantikan useState?
Tidak sepenuhnya. useRef tidak menyebabkan re-render, jadi hanya cocok untuk nilai yang tidak memengaruhi tampilan UI.

5. Apakah perlu menghafal semua hooks?
Tidak perlu. Kuasai dulu yang utama. Seiring waktu, kamu akan mengenal hooks tambahan sesuai kebutuhan proyekmu.

Komentar

Belum ada komentar.