Reactjs Hooks Usestate Useeffect Usememo Usecallback Useref
Selesai membaca dokumentasi ini?
Kembali ke rujukan utama React.js untuk melanjutkan topik lainnya.
Kembali ke rujukan utama React.js untuk melanjutkan topik lainnya.
Hooks adalah API fungsi di React yang dipakai untuk memberi komponen fungsional kemampuan seperti menyimpan state, menjalankan side effect, menyimpan referensi nilai lintas render, dan mengoptimalkan nilai atau fungsi yang mahal untuk dihitung ulang.
Lima hooks dasar yang paling sering muncul di komponen aplikasi nyata adalah:
useState untuk state lokal yang memicu rerender.useEffect untuk sinkronisasi dengan dunia luar setelah render.useMemo untuk menyimpan hasil perhitungan agar tidak dihitung ulang setiap render.useCallback untuk menyimpan referensi fungsi agar stabil antar render.useRef untuk menyimpan nilai mutable atau referensi DOM tanpa memicu rerender.Kalau dipakai dengan tepat, hooks membuat komponen tetap kecil, terukur, dan mudah di-debug. Kalau dipakai asal, masalah yang muncul biasanya bukan error sintaks, melainkan rerender berulang, dependency array yang salah, atau efek yang jalan di waktu yang tidak diinginkan.
Inti yang perlu diingat:
useState mengubah data yang memicu render.useEffect biasanya dijalankan sesudah render selesai tampil.useMemo dan useCallback tidak menghentikan render; keduanya hanya membantu menjaga hasil atau referensi tetap stabil.useRef menyimpan nilai yang bertahan antar render tanpa ikut menjadi pemicu render.Pakai useState saat komponen perlu menyimpan data yang berubah dan perubahan itu harus terlihat di UI.
Contoh umum:
Saat setState dipanggil, React menjadwalkan rerender komponen tersebut dan subtree yang bergantung pada hasil render itu.
Artinya:
import { useState } from 'react';
export default function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount
setCount(prev => prev + 1);// Hindari
user.name = 'Budi';
setUser(user);
// Lebih aman
setUser(prev => ({ ...prev, name: 'Budi' }));Pakai useEffect untuk side effect, yaitu pekerjaan yang menyentuh dunia luar dari proses render murni.
Contoh:
useEffect sendiri tidak otomatis memicu rerender. Yang memicu rerender adalah perubahan state yang dilakukan di dalam effect.
Urutan sederhananya:
useEffect dijalankan.setState, render berikutnya terjadi.import { useEffect, useState } from 'react';
export default function UserList() {
const [users, setUsers] = useState([]);
useEffect(() => {
let cancelled
Dependency array menentukan kapan effect dijalankan ulang.
[] → hanya setelah mount[a, b] → ulang kalau a atau b berubah referensinyaprops atau state, tetapi tidak dicantumkan. Akibatnya effect membaca nilai lama.Contoh loop yang sering terjadi:
useEffect(() => {
setCount(count + 1);
}, [count]);Kalau memang perlu sinkronisasi seperti ini, pikirkan ulang desain state-nya. Sering kali yang dibutuhkan bukan effect, melainkan derived state atau event handler.
useEffect.useMemo atau perhitungan biasa.Pakai useMemo saat ada perhitungan yang mahal atau saat perlu menjaga referensi hasil tetap stabil antar render.
Contoh umum:
useMemo tidak mencegah rerender komponen. Komponen tetap rerender kalau state atau props berubah.
Yang dilakukan useMemo adalah:
import { useMemo } from 'react';
export default function ProductList({ products, query }) {
const filtered = useMemo(() => {
return products.filter(product =>
product.name.
useMemo untuk semua hal. Kalau perhitungannya murah, memoization justru menambah kompleksitas.useMemo menjaga semua child dari rerender. Itu hanya benar kalau child juga memang bergantung pada referensi hasil memo itu.Gunakan useMemo sebagai optimisasi yang terukur, bukan kebiasaan default. Kalau belum ada bukti bottleneck, sederhanakan dulu.
Pakai useCallback saat perlu menjaga referensi fungsi tetap stabil, biasanya ketika fungsi itu diteruskan sebagai props ke child yang dioptimalkan dengan memo, atau dipakai sebagai dependency hook lain.
Contoh umum:
useCallback tidak menghentikan komponen induk dari rerender.
Fungsinya adalah:
memo tidak ikut rerender hanya karena referensi function bergantiimport { memo, useCallback, useState } from 'react';
const Button = memo(function Button({ onClick }) {
return <button onClick={onClick}>Tambah</button>;
});
export default
useCallback tanpa kebutuhan nyata. Kalau tidak ada child memoized atau dependency lain yang sensitif pada referensi, manfaatnya kecil.useCallback untuk “menghemat semua rerender”. Itu bukan fungsinya.useMemoSecara konsep:
useMemo menyimpan hasil nilaiuseCallback menyimpan hasil fungsiBisa dianggap useCallback(fn, deps) mirip useMemo(() => fn, deps) secara bentuk, tetapi gunakan sesuai niatnya agar kode tetap terbaca.
Pakai useRef saat perlu menyimpan sesuatu yang bertahan antar render, tetapi perubahan nilainya tidak perlu memicu rerender.
Contoh umum:
Perubahan ref.current tidak memicu rerender.
Itu bedanya yang paling penting dengan useState.
import { useEffect, useRef } from 'react';
export default function SearchInput() {
const inputRef = useRef(null);
useEffect(() => {
inputRef.current?.focus();
}, []);
return <
import { useEffect, useRef } from 'react';
export default function PreviousValue({ value }) {
const prevRef = useRef(value);
useEffect(() => {
prevRef.current = value;
}, [value]);
return <
| Hook | Dipakai untuk | Memicu rerender? | Catatan utama |
|---|---|---|---|
useState | data UI yang berubah | Ya, saat setter dipanggil | pilihan default untuk state lokal |
useEffect | side effect setelah render | Tidak langsung | hati-hati dependency array dan cleanup |
useMemo | hasil perhitungan / referensi bernilai stabil | Tidak | optimisasi, bukan alat utama |
useCallback | referensi fungsi stabil | Tidak | berguna saat passing callback ke child memoized |
useRef | nilai mutable / DOM ref | Tidak | update current tidak rerender |
Bagian ini penting karena banyak bug React bukan berasal dari hook yang salah, melainkan dependency array yang tidak sesuai.
useEffect(() => {
console.log(user.name);
}, []);Kalau user.name bisa berubah, effect ini akan terus membaca nilai awal.
const options = { mode: 'dark' };
useEffect(() => {
connect(options);
}, [options]);Karena options dibuat ulang setiap render, effect ikut jalan terus.
Solusi yang lebih rapi:
const options = useMemo(() => ({ mode: 'dark' }), []);atau pindahkan object ke dalam effect kalau memang hanya dipakai di sana.
const handleSave = () => {
saveDraft(form);
};
useEffect(() => {
register(handleSave);
}, [handleSave]);Karena handleSave baru setiap render, effect bisa terus aktif. Kalau perlu stabil, bungkus dengan useCallback.
Kalau data hanya hasil transform dari props/state, jangan simpan hasilnya ke state lalu sinkronkan lewat effect kalau tidak perlu.
Lebih sederhana:
const filtered = useMemo(() => filterItems(items, query), [items, query]);Daripada:
const [filtered, setFiltered] = useState([]);
useEffect(() => {
setFiltered(filterItems(items, query));
}, [items, query]);Pendekatan pertama biasanya lebih bersih dan lebih sedikit tempat bug.
Gunakan pertanyaan cepat ini:
useStateuseEffectuseMemouseCallbackuseRefimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';
export default function SearchDashboard({ products }) {
const [query, setQuery] = useState
Di contoh ini:
useState menyimpan query input.useRef menyimpan referensi input.useMemo menghitung hasil filter.useCallback menjaga handler stabil.useEffect menyinkronkan judul halaman.Untuk praktik sehari-hari, urutan berpikir yang aman biasanya begini:
useState untuk state yang benar-benar tampil di UI.useEffect hanya untuk side effect.useMemo dan useCallback kalau ada alasan performa atau stabilitas referensi yang jelas.useRef untuk nilai mutable dan akses DOM tanpa rerender.Kalau satu komponen mulai terasa rumit, biasanya masalahnya bukan “kurang hook”, melainkan hook dipakai untuk tugas yang tidak tepat.