useRef — adalah hook React yang membuat objek ref yang dapat diubah dengan properti .current, yang dipertahankan di antara render komponen. Tidak seperti useState, perubahan .current tidak menyebabkan render ulang, menjadikan useRef ideal untuk menyimpan referensi DOM, timer, dan nilai apa pun yang harus bertahan melewati render tanpa menggambar ulang UI. Menurut React Documentation (2025), objek ref dibuat satu kali selama masa hidup komponen dan tidak berubah di antara render, yang menjamin stabilitas referensi.
Poin utama
useRef — adalah hook yang ditambahkan di React 16.8, yang mengembalikan objek ref yang dapat diubah dengan satu properti .current. Nilai awal ditetapkan ke .current saat komponen dipasang. Perbedaan utama dari variabel biasa — objek ref bertahan dari render ulang: saat render ulang, React tidak membuat ulang ref, tetapi mengembalikan objek yang sama.
Implementasi internal useRef menggunakan mekanisme yang sama dengan useState dan useEffect — daftar hook yang terhubung pada node fiber. Namun, tidak seperti useState, React tidak melacak perubahan objek ref, tidak mengantrekan pembaruan, dan tidak menjadwalkan render ulang. Ini membuat useRef menjadi hook yang sangat ringan, tidak memengaruhi performa bahkan dengan perubahan yang sering.
Menurut React Team — Hooks FAQ (2025), useRef pada dasarnya adalah “kotak” yang menyimpan nilai. Gula sintaksis: const ref = useRef(initialValue) setara dengan const ref = { current: initialValue } dengan perbedaan bahwa React menjamin objek ref akan sama setiap kali render. Tidak ada sihir — hanya referensi stabil yang dikelola oleh React.
import { useRef } from 'react';
function Component() {
const countRef = useRef(0);
// countRef.current = 0 awalnya
// countRef.current = 5 setelah mutasi
// Tidak terjadi render ulang!
}
Skenario penggunaan useRef yang paling umum — mendapatkan akses langsung ke elemen DOM. React menetapkan elementRef.current ke referensi node DOM setelah komponen dipasang. Ini diperlukan untuk memfokuskan input, mengukur dimensi elemen, integrasi dengan library animasi, dan library yang tidak menggunakan render React.
React secara otomatis mengelola referensi ref ke DOM: saat pemasangan menetapkan node DOM yang sebenarnya, saat pelepasan meresetnya (menjadi null). Ini menjamin bahwa .current selalu berisi nilai terkini dan mencegah kebocoran memori melalui referensi “menggantung” ke elemen yang dihapus. Tidak diperlukan pembersihan manual.
function AutoFocusInput() {
const inputRef = useRef(null);
useEffect(() => {
// Fokus input setelah komponen dipasang
inputRef.current?.focus();
}, []);
return <input ref={inputRef} type="text" />;
}
Menurut React — Refs and DOM documentation (2025), jangan gunakan ref untuk operasi deklaratif — membuka/menutup modal, mengelola visibilitas. Untuk tujuan tersebut ada state dan props. Ref ditujukan untuk operasi imperatif yang tidak dapat dinyatakan secara deklaratif: fokus, seleksi teks, integrasi dengan library pihak ketiga.
Skenario terpenting kedua — menyimpan nilai arbitrer yang harus dipertahankan di antara render, tetapi perubahannya tidak boleh menyebabkan render ulang. Contoh tipikal: pengidentifikasi timer (setInterval/setTimeout), flag untuk membatalkan permintaan, nilai prop sebelumnya untuk perbandingan, dan data apa pun yang tidak memengaruhi keluaran UI.
Ini sangat berguna di useEffect: useRef menyimpan pengidentifikasi timer, dan pembersihan menghapusnya. Jika timerId disimpan di useState, setiap panggilan setTimerId akan menyebabkan render ulang yang tidak perlu yang tidak diperlukan baik untuk logika maupun UI. useRef memecahkan masalah ini tanpa overhead dan tanpa penggambaran ulang yang tidak perlu.
function Timer() {
const intervalRef = useRef(null);
const start = () => {
intervalRef.current = setInterval(() => {
console.log('detak');
}, 1000);
};
const stop = () => {
clearInterval(intervalRef.current);
};
useEffect(() => stop, []);
return <><button onClick={start}>Start</button><button onClick={stop}>Stop</button></>;
}
Dilema utama — pilihan antara useRef dan useState — diselesaikan dengan satu pertanyaan: “Apakah render ulang diperlukan saat nilai berubah?”. Jika ya — useState. Jika tidak — useRef. useState menyimpan keadaan yang memengaruhi keluaran komponen; useRef menyimpan data yang diperlukan untuk logika internal, tetapi tidak memengaruhi UI.
Dalam praktiknya, pengembang sering menggunakan useRef untuk menyimpan callback, guna menghindari masalah dengan closure. Misalnya, jika useEffect berlangganan ke suatu peristiwa dan di dalam callback diperlukan state terkini — simpan callback di useRef. Setiap render perbarui ref.current dengan fungsi baru, dan efek akan selalu memanggil callback segar tanpa berlangganan ulang.
| Kriteria | useRef | useState |
|---|---|---|
| Render ulang | Tidak menyebabkan saat perubahan | Menyebabkan setiap setState |
| Mutasi | Langsung: ref.current = value | Melalui setter: setState(value) |
| Penggunaan di JSX | Tidak digunakan (tidak ada efek) | Digunakan di keluaran komponen |
| Contoh | Timer, referensi DOM, nilai sebelumnya | Data formulir, status UI, flag |
Ada anti-pattern: menggunakan useRef untuk menyimpan data yang diperlukan di JSX, tetapi perubahannya tidak boleh menyebabkan render ulang. Ini menyebabkan desinkronisasi — UI menampilkan data lama, meskipun ref.current sudah baru. Jika nilai ditampilkan di UI — gunakan useState. Jika hanya digunakan di dalam logika — useRef.
Kombinasi useRef + useEffect — pola standar untuk melacak nilai prop sebelumnya. Simpan nilai sebelumnya di ref, bandingkan dengan nilai saat ini di useEffect, dan buat keputusan berdasarkan perbedaan. Ini sangat berguna dalam animasi, ketika Anda perlu tahu nilai apa yang ada sebelum perubahan.
function PriceDisplay({ price }) {
const prevPriceRef = useRef(price);
useEffect(() => {
const prevPrice = prevPriceRef.current;
if (price > prevPrice) {
animateUp();
} else if (price < prevPrice) {
animateDown();
}
prevPriceRef.current = price;
}, [price]);
return <span>${price}</span>;
}
Menurut React Documentation — Hooks FAQ (2025), pola ini disebut “previous value pattern”. Ini bekerja karena useRef mempertahankan nilai di antara render, dan useEffect dijalankan setelah perubahan dikonfirmasi. Pertama DOM diperbarui dengan price baru, kemudian useEffect membandingkan dengan yang sebelumnya (masih di ref) dan memperbarui ref.current ke nilai saat ini.
Kesalahan paling umum — membaca ref.current di fase render untuk menghitung JSX. Karena perubahan ref.current tidak menyebabkan render ulang, komponen mungkin menggunakan nilai yang usang. Jika nilai .current berpartisipasi dalam keluaran UI — gunakan useState. Jika perlu menyinkronkan ref dan state, gunakan useEffect untuk memperbarui state dari ref.
// ❌ Jangan baca ref.current selama render untuk ditampilkan
function BadComponent() {
const valRef = useRef(0);
return <p>{valRef.current}</p>; // TIDAK akan diperbarui saat mutasi
}
// ✅ Gunakan state untuk tampilan, ref untuk logika
function GoodComponent() {
const [val, setVal] = useState(0);
const valRef = useRef(0);
return <p>{val}</p>;
}
Kesalahan umum lainnya — menggunakan useRef sebagai satu-satunya cara menyimpan state di komponen, ketika data tetap memengaruhi UI. Pengembang memilih useRef untuk menghindari render ulang yang “tidak perlu”, tetapi pada akhirnya mendapatkan UI yang tidak diperbarui. Pendekatan yang benar: gunakan useState untuk data UI dan useRef hanya untuk nilai bantu yang tidak berpartisipasi dalam render.
Pertanyaan yang sering diajukan
Ya, ini adalah pola yang umum — previous state pattern. Buat ref dan perbarui di useEffect setiap kali nilai yang dilacak berubah. Pada momen antara render dan efek, ref.current berisi nilai sebelumnya yang dapat dibandingkan dengan nilai saat ini. Ini tidak memerlukan render ulang tambahan dan bekerja dengan semua jenis data.
React menetapkan ref.current nilai node DOM hanya setelah elemen di-render dan ditambahkan ke DOM nyata. Selama render pertama, komponen belum dipasang, oleh karena itu ref.current sama dengan nilai awal (null). Akses ke DOM melalui ref.current hanya mungkin di useEffect atau di handler peristiwa yang dipanggil setelah pemasangan.
createRef membuat objek ref baru setiap render — hanya boleh digunakan di komponen kelas. useRef membuat ref sekali dan mengembalikan objek yang sama di semua render berikutnya. Di komponen fungsional gunakan exclusively useRef; createRef akan menyebabkan hilangnya nilai saat render ulang, karena objek akan dibuat ulang.
Ya, objek ref dapat diteruskan sebagai prop biasa: <Child inputRef={inputRef} />. Komponen anak menggunakannya melalui inputRef.current. Namun, untuk meneruskan ref langsung ke elemen DOM komponen anak, gunakan forwardRef — HOC yang memungkinkan ref melewati props. Tanpa forwardRef, ref tidak akan secara otomatis terikat ke elemen DOM di dalam komponen anak.
Ikat ref ke elemen, lalu di useEffect baca ref.current.getBoundingClientRect() atau ref.current.offsetWidth / offsetHeight. Untuk pelacakan reaktif perubahan ukuran, gunakan ResizeObserver di dalam useEffect: buat observer, berlangganan perubahan, dan perbarui state dengan ukuran baru. Jangan lupa nonaktifkan observer di pembersihan.
Ringkasan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga