useRef
useEffect dersinde, component'in ekran çıktısı dışında bir şey yapmasını
gördük. Bu ders, benzer bir ihtiyaca -- ekranı tetiklemeden bir değeri
"hatırlamak" ya da bir DOM elementine doğrudan erişmek -- çözüm sunan bir
başka hook'u, useRef'i anlatıyor.
DOM Referansları (DOM References)
useRef'in en yaygın kullanımlarından biri, bir DOM elementine doğrudan
erişmek:
import { useRef } from "react";
function DomReferenceExample() {
const inputRef = useRef(null);
function focusInput() {
// inputRef.current, gerçek DOM elementinin kendisi -- input'un
// sahip olduğu tarayıcı metotlarını (focus() gibi) doğrudan çağırabiliriz.
inputRef.current.focus();
}
return (
<div>
<input ref={inputRef} type="text" placeholder="Butona basınca odaklanır" />
<button onClick={focusInput}>Input'a Odaklan</button>
</div>
);
}
ref={inputRef} yazarak React'e "bu elementin gerçek DOM node'unu
inputRef.current'a koy" diyoruz. inputRef.current, artık gerçek bir
DOM elementi -- focus() gibi tarayıcının kendi metotlarını doğrudan
çağırabiliriz.
Render'lar Arası Kalıcı Değerler
useRef'in ikinci kullanımı: bir değeri render'lar arasında
"hatırlamak", ama bu değer değiştiğinde ekranı YENİDEN RENDER
ETMEDEN:
import { useState, useRef } from "react";
function PersistentValueExample() {
const [count, setCount] = useState(0);
const renderCount = useRef(0);
renderCount.current = renderCount.current + 1;
// renderCount.current değişiyor, ama bu bir RE-RENDER TETİKLEMEZ --
// yalnızca bir sonraki render'da güncel değeri gösterir.
return (
<div>
<p>Sayaç: {count}</p>
<p>Bu component şu ana kadar {renderCount.current} kez render oldu.</p>
<button onClick={() => setCount(count + 1)}>+1</button>
</div>
);
}
renderCount.current her render'da artıyor ve değeri render'lar arasında
korunuyor -- ama bu artış kendi başına bir re-render TETİKLEMİYOR.
Değeri yalnızca bir SONRAKİ render olduğunda (başka bir sebeple, burada
count state'i değiştiği için) güncel haliyle görüyoruz.
useRef vs useState
useRef ile useState arasındaki temel fark şu: useState'i
değiştirmek bir re-render TETİKLER, useRef'i değiştirmek TETİKLEMEZ:
import { useState, useRef } from "react";
function UseRefVsUseStateExample() {
const [stateValue, setStateValue] = useState(0);
const refValue = useRef(0);
function incrementState() {
setStateValue(stateValue + 1); // Ekranı günceller (re-render tetikler).
}
function incrementRef() {
refValue.current = refValue.current + 1;
console.log("refValue.current:", refValue.current);
// Değer gerçekten değişti, ama ekran GÜNCELLENMEZ -- çünkü ref
// değişikliği bir re-render tetiklemez.
}
return (
<div>
<p>State: {stateValue}</p>
<button onClick={incrementState}>State'i Artır</button>
<button onClick={incrementRef}>Ref'i Artır (Console'a Bak)</button>
</div>
);
}
"State'i Artır" butonuna basınca ekran güncellenir, çünkü setStateValue
bir re-render tetikler. "Ref'i Artır" butonuna basınca değer gerçekten
değişir (console'da görebilirsin), ama ekranda hiçbir şey değişmez --
çünkü ref değişikliği React'e "yeniden render et" demez. Ekranda
GÖRÜNMESİ gereken bir değer state olmalı; ekranda görünmesi gerekmeyen,
yalnızca "hatırlanması" gereken bir değer ref olabilir.
useRef ve useEffect'i Birlikte Kullanmak
useRef ve useEffect sık sık birlikte kullanılır -- örneğin, "bir
önceki render'daki değer neydi" sorusuna cevap vermek için:
import { useState, useEffect, useRef } from "react";
function PreviousValueWithRefExample() {
const [count, setCount] = useState(0);
const previousCountRef = useRef(undefined);
useEffect(() => {
// Her render'dan SONRA, mevcut değeri ref'e kaydediyoruz -- bir sonraki
// render'da "bir önceki değer" olarak okuyabilmek için. Bunun için
// state değil ref kullanıyoruz, çünkü bu kaydı ekranı yeniden
// render etmeden yapmak istiyoruz.
previousCountRef.current = count;
});
return (
<div>
<p>
Şimdiki: {count}, Önceki: {previousCountRef.current}
</p>
<button onClick={() => setCount(count + 1)}>+1</button>
</div>
);
}
Her render'dan sonra çalışan useEffect, mevcut count değerini
previousCountRef'e kaydediyor. Bir sonraki render'da, bu ref hâlâ BİR
ÖNCEKİ render'daki değeri taşıyor -- çünkü ref güncellemesi kendi başına
yeni bir render tetiklemiyor, güncelleme ancak count state'i
değiştiğinde gerçekleşen render'ın İÇİNDE oluyor.
Özet ve Terimler Sözlüğü
useRef, iki temel iş için kullanılır: bir DOM elementine doğrudan
erişmek, ya da bir değeri render'lar arasında ekranı tetiklemeden
hatırlamak. useState'in aksine, bir ref'i değiştirmek re-render
tetiklemez -- bu yüzden ekranda görünmesi gereken veriler için useState,
görünmesi gerekmeyen "arka plan" değerleri için useRef kullanılır.
Terimler Sözlüğü
useRef — Bir DOM elementine erişmeni ya da bir değeri render'lar
arasında, ekranı tetiklemeden saklamanı sağlayan hook.
.current — useRef'in döndürdüğü nesnenin, o an tutulan değeri
taşıyan alanı.
DOM Referansı — Bir JSX elementinin gerçek tarayıcı DOM node'una
doğrudan erişim; ref attribute'u ile kurulur.