useRef

DOM referansları, render'lar arası kalıcı değerler, useRef vs useState, ve useRef'i useEffect ile birlikte kullanmak -- basit örneklerle.

Orta 11 dk
EN

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.

.currentuseRef'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.