Menu

React useRef Hook'u: DOM Ref'leri ve Kalıcı Değerler

useRef bir bileşene, içeriğini render'lar arasında koruyan ve değiştirdiğinde render'a yol açmayan bir kutu, { current }, verir. Onu bir DOM düğümüne ulaşmak (odaklama, kaydırma, ölçme) ya da bir zamanlayıcı id'sini veya ekranın göstermediği herhangi bir değeri saklamak için kullan.

Bu sayfada çalıştırılabilir editörler var - düzenle, çalıştır ve sonucu anında gör.

useRef, React'in bileşenin ömrü boyunca koruduğu bir nesne döndürür: { current: initialValue }. ref.current'ı değiştirmek hiçbir şeyi yeniden render etmez. Bu da ref'leri iki iş için doğru araç yapar: üzerinde focus() gibi metotları çağırabilmek için bir DOM düğümünü tutmak ve ekranın göstermesi gerekmeyen bir değeri render'lar arasında hatırlamak.

Ref nesnesini ref={inputRef}'e aktarmak React'e <input> DOM düğümünü inputRef.current'a koymasını söyler. focus()'u select() yap, bir şey yaz ve yeniden tıkla: metin vurgulanır.

Sözdizimi

const myRef = useRef(initialValue);

myRef.current;          // read
myRef.current = value;  // write, no re-render
  • initialValue yalnızca ilk render'da kullanılır. DOM ref'leri için null'dır.
  • React her render'da aynı nesneyi döndürür. Yalnızca current değişir.
  • current'ı okumak ve yazmak sıradan JavaScript'tir. React onu takip etmez.

Render'a yol açmayan bir değer

State ekranın gösterdiği şey içindir. Ref ise bileşenin hatırlaması ama göstermemesi gereken şey içindir. Bu blok bir sayacı bir ref'te, birini state'te tutar ve ikisini de kaydeder:

Ref + 1'e birkaç kez tıkla. Konsol ref.current'ın arttığını gösterir, ama sayfa hâlâ 0 der ve hiçbir render kaydedilmez. Şimdi State + 1'e tıkla: bileşen render olur ve ekrandaki ref sayacı ref'in zaten tuttuğu sayıya atlar. Ref değerini baştan beri korudu; React'in onu çizmek için bir nedeni yoktu.

Ref'ler ve state

useStateuseRef
Döndürür[value, setValue]{ current: value }
DeğiştirmekBileşeni yeniden render ederGörünür hiçbir şey yapmaz
Yeni değer ne zaman okunabilirSonraki render'daHemen
Nasıl değiştirilirSetter ileAtama ile, ref.current = x
KullanımEkranın gösterdiği her şeyZamanlayıcı id'leri, DOM düğümleri, önceki değerler, bayraklar

Emin değilsen JSX'in değeri okuyup okumadığını sor. Okuyorsa state'e aittir.

Bir zamanlayıcı id'sini saklamak

setInterval, zamanlayıcıyı durdurmak için sonra ihtiyaç duyacağın bir id döndürür. Bu bir ref için iyi bir örnektir: Stop işleyicisinin ona ihtiyacı vardır, ama ekran onu hiç göstermez ve onu düz bir değişkende tutmak bir sonraki render'da onu kaybettirirdi.

useRef(null)'ı let intervalRef = { current: null }; ile değiştir ve Start'ı dene, iki saniye bekle, sonra Stop: zamanlayıcı devam eder. Her tik bileşeni render eder, bu da taze bir nesne oluşturur, bu yüzden Stop hiçbir şeyi temizlemez.

Önceki değeri hatırlamak

Bir efekt render'dan sonra çalışır, bu yüzden yeni değeri bir ref'te saklanan değerle karşılaştırabilir, sonra yenisini bir dahaki sefer için kaydedebilir:

Önce green'e, sonra blue'ya tıkla: konsol changed from red to green ve changed from green to blue yazar. Zaten seçili olan renge tıklamak hiçbir şey yazmaz, çünkü efekt yalnızca color değiştiğinde çalışır.

DOM ile çalışmak

Ref'ler, React'in prop'unu sunmadığı tarayıcı API'lerini çağırmanın yoludur: focus(), select(), scrollIntoView(), bir videoda play() ya da getBoundingClientRect() ile bir boyutu okumak.

const lastItemRef = useRef(null);

function scrollToLast() {
    lastItemRef.current.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
}

<li ref={lastItemRef}>Last item</li>

ref.current ilk render sırasında null'dır, çünkü React DOM düğümünü henüz oluşturmamıştır, öğe kaldırıldıktan sonra da yeniden null olur. Onu düğümün var olduğu olay işleyicilerinde ve efektlerde oku. Bir öğeyi ölçüp tarayıcı boyamadan önce bir şeyi konumlandırmak için ref'i useLayoutEffect içinde oku.

Render sırasında ref.current okuma ya da yazma

React bileşen gövdesinin saf bir hesaplama olmasını bekler: aynı props ve state, aynı JSX. Bir ref bu modelin dışında değişir, bu yüzden onu okuyan ya da yazan bir render aynı girdiler için farklı sonuçlar gösterebilir ve React gövdeyi beklediğinden daha sık çağırabilir.

function Bad() {
    const count = useRef(0);
    count.current++;              // writing during render
    return <p>{count.current}</p>; // reading during render
}

Ref'leri olay işleyicilerinde ve efektlerde oku ve yaz. Tek istisna, ref'i ilk render'da bir kez doldurduğun lazy başlatmadır:

const playerRef = useRef(null);
if (playerRef.current === null) {
    playerRef.current = new VideoPlayer(); // runs once
}

(Yukarıdaki ref sayacı demosu, ekranın onu takip etmediğini göstermek için JSX'te bilerek clicks.current'ı okuyor. Bunu gerçek koda kopyalama.)

Ref callback'leri

Bir ref nesnesi yerine ref'e bir fonksiyon aktarabilirsin. React öğe eklendiğinde onu DOM düğümüyle çağırır. React 19'da fonksiyon bir temizleme döndürebilir; React onu öğe kaldırıldığında çağırır. Bu, her öğe için bir kez useRef çağıramadığın bir liste için kullanışlıdır:

Yüklenince konsol her öğe için bir attached satırı yazar. Remove last'a tıkla, yalnızca detached Cheese görünür. trackNode bileşenin dışında tanımlanmıştır, bu yüzden her render'da aynı fonksiyondur ve React diğer öğelere dokunmaz. Bunun yerine onu satır içinde ref={(node) => { ... }} olarak yaz; her tıklama her öğeyi ayırıp yeniden bağlar, çünkü her render yeni bir fonksiyon aktarır.

Kendi bileşenine ref aktarmak

React 19'da ref, fonksiyon bileşenleri için normal bir prop'tur. Ebeveyn ref'i oluşturur, çocuk da onu açığa çıkarmak istediği DOM öğesine koyar:

React 19'dan önce bu, hâlâ çalışan forwardRef'i gerektiriyordu. forwardRef sayfası iki sürümü ve useImperativeHandle ile yalnızca birkaç metodu nasıl açığa çıkaracağını gösteriyor.

Yaygın hatalar

Bir ref değerini JSX'te göstermek. Ekran onu takip etmez. Kullanıcının değeri görmesi gerekiyorsa state kullan.

ref.current'ı bir efekt bağımlılığı olarak kullanmak. [ref.current] değeri render sırasında okur ve React onun ne zaman değiştiğini bilmez, bu yüzden değiştiğinde efekt yeniden çalışmaz. Bir düğümün bağlanmasına tepki vermek için bir ref callback'i kullan.

İlk render sırasında bir DOM ref'ini okumak. React düğümü oluşturana kadar null'dır. Onu bir efektte ya da bir işleyicide oku.

Hook'u kullanmak yerine yeni bir nesne oluşturmak. Bileşen gövdesindeki const ref = { current: null } her render'da taze bir nesnedir. Sana her seferinde aynısını yalnızca useRef verir.

Sıkça Sorulan Sorular

useRef ne döndürür?

Tek bir özelliği, current, olan ve aktardığın başlangıç değerine ayarlanmış düz bir nesne. React her render'da aynı nesneyi döndürür, bu yüzden current'a ne koyarsan bir dahaki sefere hâlâ oradadır.

useRef ile useState arasındaki fark nedir?

State'i değiştirmek bileşeni yeniden render eder; ref.current'ı değiştirmek etmez. Ekranın gösterdiği değerler için state, yalnızca olay işleyicilerinin ve efektlerinin ihtiyaç duyduğu değerler için ise bir ref kullan, örneğin bir zamanlayıcı id'si ya da bir DOM düğümü.

ref.current neden null?

React düğümü oluşturduktan sonra, commit sırasında ref.current'ı DOM düğümüne ayarlar. İlk render sırasında hâlâ null'dır ve öğe kaldırıldıktan sonra yeniden null olur. Onu bir olay işleyicisinde ya da bir efektte oku.

ref.current'ı değiştirmek yeniden render'a yol açar mı?

Hayır. React onu değiştirdiğini bilmez. Yeni değer ancak başka bir şey, örneğin bir state güncellemesi, bileşeni yeniden render ederse ekranda görünür.

Bir çocuk bileşene ref nasıl aktarılır?

React 19'da bir fonksiyon bileşeni ref'i normal bir prop olarak alır, bu yüzden <MyInput ref={inputRef} /> aktarırsın ve çocuk onu kendi <input>'una koyar. Eski sürümler forwardRef gerektiriyordu.

Coddy programlama dilleri çizimi

Coddy ile kodlamayı öğren

BAŞLA