Penggunaan React useImperativeHandle



useImperativeHandle adalah hook di React yang digunakan untuk menyesuaikan nilai instance (metode atau properti) yang diekspos ke komponen parent ketika menggunakan ref pada komponen anak. Hook ini umumnya dipakai bersama forwardRef untuk mengontrol perilaku komponen anak secara imperatif (seperti memanggil fungsi atau mengakses nilai langsung).
Kapan Menggunakan useImperativeHandle?
- Saat ingin membatasi akses parent ke metode/properti tertentu dari komponen anak.
- Untuk integrasi dengan library eksternal (misalnya, mengontrol DOM element secara imperatif).
- Ketika perlu mengakses fungsi komponen anak secara langsung (contoh: fokus input, play/pause video).
Sintaks Dasar
useImperativeHandle(ref, () => ({
// Metode/properti yang ingin diekspos ke parent
}), [dependencies]);
Contoh Penggunaan
1. Komponen Anak dengan Metode Imperatif
import { forwardRef, useImperativeHandle, useRef } from 'react';
// Komponen anak menggunakan forwardRef
const CustomInput = forwardRef((props, ref) => {
const inputRef = useRef();
// Ekspos metode focus dan getValue ke parent
useImperativeHandle(ref, () => ({
focus: () => inputRef.current.focus(),
getValue: () => inputRef.current.value,
}), []); // Dependency array kosong → hanya dijalankan sekali
return <input ref={inputRef} {...props} />;
});
// Komponen Parent
function Parent() {
const inputRef = useRef();
const handleClick = () => {
inputRef.current.focus(); // Panggil metode focus dari parent
console.log('Nilai input:', inputRef.current.getValue());
};
return (
<div>
<CustomInput ref={inputRef} />
<button onClick={handleClick}>Fokus Input</button>
</div>
);
}
2. Integrasi dengan Video Player
const VideoPlayer = forwardRef((props, ref) => {
const videoRef = useRef();
useImperativeHandle(ref, () => ({
play: () => videoRef.current.play(),
pause: () => videoRef.current.pause(),
isPlaying: () => !videoRef.current.paused,
}), []);
return <video ref={videoRef} src="video.mp4" />;
});
function App() {
const playerRef = useRef();
return (
<div>
<VideoPlayer ref={playerRef} />
<button onClick={() => playerRef.current.play()}>Play</button>
<button onClick={() => playerRef.current.pause()}>Pause</button>
</div>
);
}
Aturan Penting
-
Wajib Digunakan dengan forwardRef
Komponen anak harus dibungkus dengan forwardRef untuk menerima ref dari parent. -
Hanya Ekspos yang Diperlukan
Batasi metode/properti yang diekspos untuk mengurangi kompleksitas. -
Perhatikan Dependency Array
Jika metode bergantung pada nilai state/props, tambahkan ke dependency array:const [count, setCount] = useState(0); useImperativeHandle(ref, () => ({ getCount: () => count, // Perbarui saat <code>count</code> berubah }), [count]);
Perbandingan useImperativeHandle vs. ref Biasa
Kriteria | useImperativeHandle | ref Biasa |
---|---|---|
Akses ke Instance | Terbatas (hanya yang diekspos) | Full akses ke DOM/node |
Kontrol | Parent mengontrol secara terbatas | Parent bisa manipulasi langsung |
Kasus Penggunaan | Komponen dengan API spesifik | Integrasi DOM/library eksternal |
Best Practices
- Gunakan untuk Kasus Spesifik: Hindari penggunaan berlebihan. Sebisa mungkin, gunakan komunikasi data via props/state.
- Encapsulation: Sembunyikan detail internal komponen anak.
- Type Safety (TypeScript): Jika menggunakan TypeScript, definisikan tipe untuk ref:
type VideoPlayerHandle = { play: () => void; pause: () => void; isPlaying: () => boolean; }; const VideoPlayer = forwardRef<VideoPlayerHandle>((props, ref) => { // ... });
Kesalahan Umum
-
Lupa Dependency Array
Jika metode bergantung pada nilai yang berubah, pastikan untuk menambahkannya ke dependency array untuk menghindari stale closure. -
Ekspos Seluruh Instance
Jangan mengekspos semua metode DOM (misal: ref.current langsung), karena bisa menyebabkan ketidakkonsistenan.
Kesimpulan
useImperativeHandle berguna ketika:
- Parent perlu mengontrol komponen anak secara imperatif.
- Anda ingin membatasi akses parent ke fungsi tertentu.
- Berintegrasi dengan library pihak ketiga yang memerlukan ref.
Gunakan dengan bijak untuk menjaga prinsip enkapsulasi dan keterbacaan kode! 🛠️