Penggunaan React useCallback



useCallback adalah hook di React yang digunakan untuk memoize (menyimpan cache) fungsi, sehingga fungsi tersebut tidak dibuat ulang setiap kali komponen dirender ulang, kecuali jika dependency-nya berubah. Ini berguna untuk mengoptimalkan performa, terutama ketika:
- Fungsi di-pass sebagai prop ke komponen anak yang menggunakan optimasi seperti React.memo.
- Fungsi menjadi dependency di hook lain (seperti useEffect).
1. Sintaks Dasar
const memoizedCallback = useCallback(
() => { /* fungsi */ },
[dependency1, dependency2] // Array dependency
);
2. Contoh Penggunaan
a. Mencegah Re-render Komponen Anak
import { useCallback, useState } from 'react';
// Komponen anak dengan React.memo
const ChildButton = React.memo(({ onClick }) => {
console.log('Child dirender ulang');
return <button onClick={onClick}>Klik Saya</button>;
});
function Parent() {
const [count, setCount] = useState(0);
// Tanpa useCallback:
// const handleClick = () => setCount(count + 1);
// Dengan useCallback (fungsi tidak dibuat ulang jika <code>count</code> tidak berubah):
const handleClick = useCallback(() => {
setCount(count + 1);
}, [count]); // Recreate jika <code>count</code> berubah
return (
<div>
<p>Hitungan: {count}</p>
<ChildButton onClick={handleClick} />
</div>
);
}
b. Digunakan dengan useEffect
function DataFetcher({ userId }) {
const [data, setData] = useState(null);
// Fungsi fetchData tidak dibuat ulang kecuali <code>userId</code> berubah
const fetchData = useCallback(async () => {
const response = await fetch(<code>https://api.example.com/users/${userId}</code>);
setData(await response.json());
}, [userId]); // Dependency: userId
useEffect(() => {
fetchData();
}, [fetchData]); // Efek dijalankan hanya jika fetchData berubah
return <div>{data ? data.name : 'Loading...'}</div>;
}
3. Kapan Menggunakan useCallback?
- Saat fungsi di-pass ke komponen anak yang dioptimasi dengan React.memo.
- Ketika fungsi menjadi dependency di hook lain (misal: useEffect, useMemo).
- Untuk mencegah re-render tidak perlu akibat perubahan referensi fungsi.
4. Perbedaan useCallback vs useMemo
Kriteria | useCallback | useMemo |
---|---|---|
Return Value | Memoize fungsi | Memoize nilai hasil fungsi |
Contoh | useCallback(() => {}, []) | useMemo(() => 100, []) |
Penggunaan | Untuk callback/event handler | Untuk nilai komputasi berat |
5. Best Practices
-
Jangan Overuse
Gunakan hanya jika benar-benar diperlukan. Overuse bisa meningkatkan penggunaan memori. -
Perhatikan Dependency Array
Pastikan semua dependency yang digunakan di fungsi dimasukkan ke array:// ❌ Salah (stale closure jika <code>count</code> berubah) const increment = useCallback(() => setCount(count + 1), []); // ✅ Benar const increment = useCallback(() => setCount(count + 1), [count]);
-
Kombinasikan dengan React.memo
Untuk komponen anak yang menerima fungsi sebagai prop:const Child = React.memo(({ onClick }) => ( <button onClick={onClick}>Child</button> ));
6. Contoh Kasus: Form Input dengan Validasi
function Form() {
const [name, setName] = useState('');
// Validasi tidak dibuat ulang kecuali dependency berubah
const validateName = useCallback((value) => {
return value.length >= 3;
}, []); // Tidak ada dependency → fungsi tetap sama
const handleSubmit = useCallback(
(e) => {
e.preventDefault();
if (validateName(name)) {
alert(<code>Nama valid: ${name}</code>);
}
},
[name, validateName] // Dependency: name dan validateName
);
return (
<form onSubmit={handleSubmit}>
<input
value={name}
onChange={(e) => setName(e.target.value)}
/>
<button type="submit">Submit</button>
</form>
);
}
7. Kesalahan Umum
a. Lupa Dependency Array
Fungsi akan selalu dibuat ulang:
const log = useCallback(() => console.log(count)); // ❌ Tidak ada dependency array
b. Dependency Array Kosong
Menyebabkan stale closure (nilai state tidak update):
const increment = useCallback(() => setCount(count + 1), []); // ❌
Solusi:
Gunakan functional update untuk state yang bergantung pada nilai sebelumnya:
const increment = useCallback(() => {
setCount(prev => prev + 1); // ✅ Tidak perlu dependency <code>count</code>
}, []);
Kesimpulan
Gunakan useCallback untuk:
- Mengoptimalkan komponen yang menerima fungsi sebagai prop.
- Mencegah efek samping tidak perlu di useEffect.
- Memastikan referensi fungsi tetap stabil selama dependency tidak berubah.
Hindari penggunaannya jika tidak diperlukan untuk mencegah kompleksitas yang tidak perlu!