useRef
useRef
adalah sebuah React Hook yang memungkinkan Anda mereferensikan sebuah nilai yang tidak diperlukan untuk rendering.
const ref = useRef(initialValue)
Referensi
useRef(initialValue)
Panggil useRef
di tingkat atas komponen Anda untuk mendeklarasikan sebuah ref.
import { useRef } from 'react';
function MyComponent() {
const intervalRef = useRef(0);
const inputRef = useRef(null);
// ...
Lihat lebih banyak contoh di bawah ini.
Parameters
initialValue
: Nilai yang Anda inginkan untuk properticurrent
objek ref pada awalnya. Nilai ini dapat berupa nilai dari jenis apa pun. Argumen ini akan diabaikan setelah render awal.
Returns
useRef
mengembalikan sebuah objek dengan satu properti:
current
: Awalnya, ini diatur keinitialValue
yang telah Anda oper. Anda dapat mengaturnya ke nilai yang lain. Jika Anda mengoper objek ref ke React sebagai sebuah atributref
ke node JSX, React akan menyetelkan properticurrent
-nya.
Pada render berikutnya, useRef
akan mengembalikan objek yang sama.
Perhatian
- Anda dapat mengubah properti
ref.current
. Tidak seperti state, properti ini tidak dapat diubah. Namun, jika properti ini menyimpan objek yang digunakan untuk rendering (misalnya, sebuah bagian dari state Anda), maka Anda tidak boleh mengubah objek tersebut. - Ketika Anda mengubah properti
ref.current
, React tidak me-render ulang komponen Anda. React tidak mengetahui kapan Anda mengubahnya karena ref adalah objek JavaScript biasa. - Jangan menulis atau membaca
ref.current
selama proses rendering, kecuali untuk inisialisasi. Hal ini membuat perilaku komponen Anda tidak dapat diprediksi. - Dalam Strict Mode, React akan memanggil fungsi komponen Anda dua kali untuk membantu Anda menemukan bug yang tidak disengaja. Ini adalah perilaku khusus development dan tidak mempengaruhi produksi. Setiap objek ref akan dibuat dua kali, tetapi salah satu versi akan dibuang. Jika fungsi komponen Anda murni (sebagaimana mestinya), hal ini seharusnya tidak mempengaruhi perilaku.
Penggunaan
Mereferensikan sebuah nilai dengan sebuah ref
Panggil useRef
di tingkat atas komponen Anda untuk mendeklarasikan satu atau lebih ref.
import { useRef } from 'react';
function Stopwatch() {
const intervalRef = useRef(0);
// ...
useRef
mengembalikan sebuah objek ref dengan satu properti current
pada awalnya diatur ke initialValue yang Anda sediakan.
Pada render berikutnya, useRef
akan mengembalikan objek yang sama. Anda dapat mengubah properti current
untuk menyimpan informasi dan membacanya nanti. Hal ini mungkin mengingatkan Anda pada state, tetapi ada sebuah perbedaan penting.
Mengubah sebuah ref tidak memicu render ulang. Ini berarti ref sangat cocok untuk menyimpan informasi yang tidak memengaruhi keluaran visual komponen Anda. Sebagai contoh, jika Anda perlu menyimpan sebuah ID interval dan mengambilnya nanti, Anda bisa menaruhnya di dalam ref. Untuk pembaruan nilai di dalam ref, Anda perlu mengubah secara manual nilai properti current
:
function handleStartClick() {
const intervalId = setInterval(() => {
// ...
}, 1000);
intervalRef.current = intervalId;
}
Nantinya, Anda dapat membaca ID interval tersebut dari ref sehingga Anda dapat memanggil pembersihan interval tersebut:
function handleStopClick() {
const intervalId = intervalRef.current;
clearInterval(intervalId);
}
Dengan menggunakan ref, Anda memastikan bahwa:
- Anda dapat menyimpan informasi di antara render ulang (tidak seperti variabel biasa, yang disetel ulang pada setiap render).
- Mengubahnya tidak memicu sebuah render ulang (tidak seperti variabel state, yang memicu sebuah render ulang).
- Informasinya bersifat lokal untuk setiap salinan komponen Anda (tidak seperti variabel di luar, yang dibagikan).
Mengubah sebuah ref tidak akan memicu sebuah render ulang, jadi ref tidak sesuai untuk menyimpan informasi yang ingin Anda tampilkan di layar. Gunakan state untuk itu. Baca lebih lanjut tentang memilih antara useRef
dan useState
.
Contoh 1 dari 2: Klik penghitung
Komponen ini menggunakan sebuah ref untuk melacak berapa kali tombol diklik. Perhatikan bahwa tidak masalah untuk menggunakan sebuah ref dan bukan state di sini karena jumlah klik hanya dibaca dan ditulis di dalam event handler.
import { useRef } from 'react'; export default function Counter() { let ref = useRef(0); function handleClick() { ref.current = ref.current + 1; alert('You clicked ' + ref.current + ' times!'); } return ( <button onClick={handleClick}> Click me! </button> ); }
Jika Anda menampilkan {ref.current}
di dalam JSX, nomor tersebut tidak akan memperbarui saat mengeklik. Hal ini karena pengaturan ref.current
tidak memicu sebuah render ulang. Informasi yang digunakan untuk rendering harus berupa state.
Memanipulasi DOM dengan sebuah ref
Sangat umum menggunakan sebuah ref untuk memanipulasi DOM. React memiliki dukungan bawaan untuk hal ini.
Pertama, deklarasikan sebuah objek ref dengan sebuah initialValue dari null
:
import { useRef } from 'react';
function MyComponent() {
const inputRef = useRef(null);
// ...
Kemudian oper objek ref Anda sebagai atribut ref
ke JSX milik node DOM yang ingin Anda manipulasi:
// ...
return <input ref={inputRef} />;
Setelah React membuat node DOM dan meletakkannya di layar, React akan mengatur properti current
objek Anda yang merujuk ke node DOM tersebut. Sekarang Anda dapat mengakses node DOM dari <input>
dan memanggil method seperti focus()
:
function handleClick() {
inputRef.current.focus();
}
React akan menyetel properti current
kembali ke null
ketika node dihapus dari layar.
Baca lebih lanjut tentang [memanipulasi DOM dengan ref].(/learn/manipulating-the-dom-with-refs)
Contoh 1 dari 4: Memfokuskan sebuah masukan teks
Dalam contoh ini, mengeklik tombol akan memfokuskan masukan:
import { useRef } from 'react'; export default function Form() { const inputRef = useRef(null); function handleClick() { inputRef.current.focus(); } return ( <> <input ref={inputRef} /> <button onClick={handleClick}> Focus the input </button> </> ); }
Menghindari pembuatan ulang konten ref
React menyimpan nilai ref awal sekali dan mengabaikannya pada render berikutnya.
function Video() {
const playerRef = useRef(new VideoPlayer());
// ...
Meskipun hasil dari new VideoPlayer()
hanya digunakan untuk render awal, Anda masih memanggil fungsi ini pada setiap render. Hal ini dapat menjadi boros jika Anda membuat objek yang besar.
Untuk mengatasinya, Anda dapat menginisialisasi ref seperti ini sebagai gantinya:
function Video() {
const playerRef = useRef(null);
if (playerRef.current === null) {
playerRef.current = new VideoPlayer();
}
// ...
Biasanya, menulis atau membaca ref.current
selama render tidak diperbolehkan. Namun, dalam kasus ini tidak masalah karena hasilnya akan selalu sama, dan kondisi ini hanya dijalankan selama inisialisasi sehingga dapat sepenuhnya diprediksi.
Pendalaman
Jika Anda menggunakan pemeriksa tipe dan tidak ingin selalu memeriksa null
, Anda dapat mencoba pola seperti ini:
function Video() {
const playerRef = useRef(null);
function getPlayer() {
if (playerRef.current !== null) {
return playerRef.current;
}
const player = new VideoPlayer();
playerRef.current = player;
return player;
}
// ...
Di sini, playerRef
itu sendiri dapat bernilai null. Namun, Anda harus dapat meyakinkan pemeriksa tipe Anda bahwa tidak ada kasus di mana getPlayer()
mengembalikan null
. Kemudian gunakan getPlayer()
di dalam event handler Anda.
Pemecahan masalah
Saya tidak bisa mendapatkan ref ke komponen kustom
Jika Anda mencoba mengoper ref
ke komponen Anda sendiri seperti ini:
const inputRef = useRef(null);
return <MyInput ref={inputRef} />;
Anda mungkin mendapatkan error di konsol:
Secara bawaan, komponen Anda sendiri tidak mengekspos ref ke node DOM di dalamnya.
Untuk memperbaikinya, cari komponen yang ingin Anda dapatkan ref-nya:
export default function MyInput({ value, onChange }) {
return (
<input
value={value}
onChange={onChange}
/>
);
}
Dan kemudian membungkusnya dengan forwardRef
seperti ini:
import { forwardRef } from 'react';
const MyInput = forwardRef(({ value, onChange }, ref) => {
return (
<input
value={value}
onChange={onChange}
ref={ref}
/>
);
});
export default MyInput;
Kemudian komponen induk bisa mendapatkan ref ke sana.
Baca lebih lanjut tentang mengakses node DOM komponen lain.