Takip et

Today I Truly Understood the useRef Hook (Not Just What It Does, But Why It Exists)

Mevcut Sayı: {count}

Today I Truly Understood the useRef Hook (Not Just What It Does, But Why It Exists)

React geliştiricilerinin yolculuğunda, useState ve useEffect gibi hook’lar genellikle ilk öğrenilen ve en sık kullanılan araçlardır. Ancak useRef hook’u, ilk bakışta sadece DOM elementlerine erişmek için basit bir mekanizma gibi görünse de, aslında çok daha derin bir amaca hizmet eder ve React’in deklaratif doğası ile imperatif dünya arasındaki kritik bir köprüdür. Bu makale, useRef‘in sadece ne işe yaradığını değil, neden var olduğunu, hangi sorunları çözdüğünü ve React ekosistemindeki gerçek yerini anlamanıza yardımcı olmayı amaçlamaktadır.

useRef Nedir? Yüzeydeki Anlamı

useRef hook’u, React fonksiyonel bileşenlerinde mutable (değiştirilebilir) bir değer tutmak için kullanılan bir araçtır. Fonksiyonel bileşenler her render edildiğinde baştan sona çalışır ve yerel değişkenler her seferinde yeniden başlatılır. useRef ise, bileşenin yaşam döngüsü boyunca değerini koruyan ve her render’da sıfırlanmayan bir referans objesi sağlar.

DOM Referanslarına Erişim

useRef‘in en yaygın ve bilinen kullanım alanı, doğrudan bir DOM elementine referans almak ve ona imperatif olarak erişmektir. Örneğin, bir input alanına odaklanmak, bir medya oynatıcıyı kontrol etmek veya bir animasyonu başlatmak gibi durumlarda useRef kullanılır. React, genellikle DOM’u doğrudan manipüle etmekten kaçınsa da, bazı durumlarda bu tür doğrudan erişim kaçınılmaz hale gelir.

ref Niteliği ile Bağlantı

Bir useRef objesini bir DOM elementine bağlamak için, JSX içindeki elemente ref niteliği atanır. Bu, React’in ilgili DOM düğümünü useRef objesinin current özelliğine atamasını sağlar.


import React, { useRef } from 'react';

function MyComponent() {
  const inputRef = useRef(null);

  const handleClick = () => {
    inputRef.current.focus(); // input elementine odaklan
  };

  return (
    
); }

current Özelliği

useRef hook'u, current adında tek bir özelliğe sahip basit bir JavaScript objesi döndürür. Bu current özelliği, referans alınan değeri veya DOM elementini tutar. useRef(initialValue) çağrıldığında, initialValue değeri current özelliğine atanır. Bu değer, bileşen yeniden render edildiğinde bile korunur.

useRef Neden Var? Temel İhtiyaç ve Felsefesi

useRef'in varoluş nedeni, React'in deklaratif doğası ile bazı imperatif gereksinimler arasındaki boşluğu doldurmaktır. React, genellikle UI'nın nasıl görüneceğini state'e göre tanımlamanızı isterken, bazen doğrudan bir şey "yapmanız" gerekir.

React'in Deklaratif Yapısı

React, UI'yı state'in bir fonksiyonu olarak tanımladığınız deklaratif bir kütüphanedir. Siz state'i değiştirirsiniz, React ise bu değişikliğe göre DOM'u günceller. Bu yaklaşım, karmaşık UI'ları yönetmeyi çok daha kolay hale getirir çünkü doğrudan DOM manipülasyonuyla uğraşmak zorunda kalmazsınız.

İmperatif İşlemler İçin Bir Köprü

Ancak bazı durumlarda, deklaratif yaklaşım yeterli olmaz. Örneğin, bir input alanına odaklanmak, bir video oynatıcıyı durdurmak veya bir canvas üzerinde çizim yapmak gibi işlemler doğrudan DOM API'leri aracılığıyla yapılır ve bunlar imperatif işlemlerdir. useRef, React'in deklaratif dünyasından çıkıp bu tür imperatif işlemleri güvenli bir şekilde gerçekleştirmemizi sağlayan bir köprü görevi görür.

Component Yaşam Döngüsü Boyunca Değerleri Korumak

useRef'in daha az bilinen ancak kritik bir kullanım alanı, bileşenin yeniden render edilmesi durumunda bile belirli bir değeri korumaktır. useState'in aksine, useRef'in current özelliğini değiştirmek bileşenin yeniden render edilmesini tetiklemez. Bu özellik, özellikle performans açısından kritik durumlarda veya UI'yı etkilemeyen arka plan değerlerini saklamak için çok değerlidir.

useRef Kullanım Alanları: Ref'lere Erişmek

DOM referanslarına erişim, useRef'in en temel ve anlaşılır kullanım senaryosudur.

Odaklanma (Focus) Yönetimi

Bir formda belirli bir input alanına otomatik odaklanma veya bir düğmeye tıklandığında başka bir alana odaklanma gibi senaryolarda useRef kullanılır.


import React, { useRef, useEffect } from 'react';

function FocusInput() {
  const inputRef = useRef(null);

  useEffect(() => {
    // Bileşen yüklendiğinde input'a otomatik odaklan
    inputRef.current.focus();
  }, []); // Sadece bir kez çalışır

  return (
    
); }

Medya Oynatıcı Kontrolü

Bir veya elementi üzerinde oynatma, duraklatma, ses seviyesini ayarlama gibi kontrolleri uygulamak için de useRef'ten faydalanılır.


import React, { useRef } from 'react';

function VideoPlayer() {
  const videoRef = useRef(null);

  const playVideo = () => {
    videoRef.current.play();
  };

  const pauseVideo = () => {
    videoRef.current.pause();
  };

  return (
    
Tarayıcınız video etiketini desteklemiyor. movie.mp4
); }

Üçüncü Parti Kütüphanelerle Entegrasyon

Bazı üçüncü parti kütüphaneler (örneğin, grafik kütüphaneleri, harita bileşenleri) DOM elementlerine doğrudan erişim gerektirebilir. useRef bu kütüphanelerin React bileşenleriyle entegrasyonunu kolaylaştırır.

useRef Kullanım Alanları: Değişken Değerleri Saklamak (Mutasyon)

useRef'in DOM dışındaki en güçlü kullanım alanlarından biri, bileşenin yaşam döngüsü boyunca mutable değerleri saklamaktır.

Yeniden Render Tetiklemeyen Değişkenler

useState'in aksine, useRef'in current özelliğini değiştirmek bileşenin yeniden render edilmesini tetiklemez. Bu, UI'yı etkilemeyen ancak bileşen içinde kalıcı olması gereken değerler için idealdir. Örneğin, bir sayaç değeri, bir zamanlayıcı kimliği veya bir önceki prop değeri gibi.

Önceki Değerleri Saklama

Bir değerin önceki halini tutmak, useEffect hook'u ile birlikte useRef kullanılarak sıkça karşılaşılan bir senaryodur.


import React, { useRef, useEffect } from 'react';

function PreviousValueDisplay({ count }) {
  const prevCountRef = useRef();

  useEffect(() => {
    prevCountRef.current = count; // Mevcut sayıyı bir sonraki render için sakla
  }, [count]); // count her değiştiğinde çalışır

  const previousCount = prevCountRef.current;

  return (
    

Mevcut Sayı: {count}

Önceki Sayı: {previousCount}

); }

Zamanlayıcı Kimlikleri (Timer IDs)

setInterval veya setTimeout gibi zamanlayıcı fonksiyonları kullanıldığında, bu zamanlayıcıları temizlemek için döndürdükleri ID'leri saklamak gerekir. useRef, bu ID'leri bileşenin yaşam döngüsü boyunca güvenli bir şekilde tutmak için mükemmel bir yerdir.


import React, { useRef, useEffect, useState } from 'react';

function TimerComponent() {
  const [count, setCount] = useState(0);
  const intervalRef = useRef(); // Zamanlayıcı ID'sini saklamak için

  useEffect(() => {
    intervalRef.current = setInterval(() => {
      setCount(prevCount => prevCount + 1);
    }, 1000);

    return () => {
      clearInterval(intervalRef.current); // Bileşen unmount olduğunda zamanlayıcıyı temizle
    };
  }, []);

  return (
    

Sayaç: {count}

); }

useRef ve Performans: Yeniden Render Etmeden Değerleri Korumak

useRef'in performansa katkısı, özellikle büyük ve karmaşık uygulamalarda göz ardı edilemez.

Gereksiz Render'ları Engelleme

Bir değer değiştiğinde bileşenin yeniden render edilmesini istemediğimiz durumlarda useRef kullanmak, useState'e göre önemli bir performans avantajı sağlar. useState ile bir değeri güncellediğinizde, React bileşeni yeniden render eder. Ancak useRef.current değerini değiştirmek, bu yeniden render işlemini tetiklemez. Bu, özellikle sık güncellenen ancak UI'yı doğrudan etkilemeyen değerler için kritik öneme sahiptir.

Hafıza Yönetimi

useRef ile oluşturulan referans objesi, bileşen hafızadan kaldırıldığında (unmount olduğunda) otomatik olarak temizlenir. Bu, hafıza sızıntılarını önlemeye yardımcı olur. Ancak current özelliğine atadığınız değerin kendisi için ek temizlik gerekebilir (örneğin, bir event listener veya bir zamanlayıcı).

Büyük Veri Setleri ve Referanslar

Bazen bir bileşen içinde büyük bir veri yapısını veya karmaşık bir objeyi tutmanız gerekebilir, ancak bu objenin her değiştiğinde bileşenin yeniden render edilmesini istemezsiniz. useRef bu tür durumlarda, objeye bir referans tutarak ve gerektiğinde doğrudan bu referans üzerinden manipülasyon yaparak performans avantajı sağlayabilir.

useRef vs. useState: Ne Zaman Hangisini Kullanmalı?

Bu iki hook arasındaki farkı anlamak, React uygulamalarında doğru aracı seçmek için hayati öneme sahiptir.

useState: UI'yı Etkileyen Durumlar

useState, bir bileşenin UI'sını etkileyen ve her değiştiğinde bileşenin yeniden render edilmesini gerektiren durumları (state) yönetmek için kullanılır. Kullanıcı etkileşimleri, veri çekme sonuçları gibi doğrudan kullanıcı arayüzünde görünür bir değişikliğe yol açan her şey useState ile yönetilmelidir.

useRef: UI'yı Doğrudan Etkilemeyen Değerler

useRef ise, aşağıdaki durumlar için tercih edilmelidir:
* DOM elementlerine doğrudan erişim gerektiğinde.
* Bileşenin yaşam döngüsü boyunca kalıcı olması gereken, ancak UI'yı etkilemeyen mutable değerleri saklamak için (örneğin, zamanlayıcı ID'leri, önceki değerler, performans sayaçları).
* Yeniden render'ı tetiklemeden bir değeri güncellemek gerektiğinde.

Ortak Kullanım Senaryoları Karşılaştırması

Aşağıdaki tablo, useState ve useRef arasındaki temel farkları özetlemektedir:

| Özellik | useState | useRef |
| :---------------- | :------------------------------------------- | :--------------------------------------------- |
| Amaç | UI durumunu yönetmek, yeniden render tetiklemek | Mutable değerleri veya DOM referanslarını tutmak |
| Render Etkisi | Değişimde bileşeni yeniden render eder | Değişimde bileşeni yeniden render etmez |
| Değer Tipi | Immutable (genellikle) | Mutable |
| Başlangıç Değeri | Her render'da yeniden başlatılır | Yalnızca ilk render'da başlatılır, sonra korunur |
| Kullanım Alanı | Form girişleri, toggle durumları, veri listeleri | DOM erişimi, zamanlayıcı ID'leri, önceki değerler |

useRef ile İlgili Dikkat Edilmesi Gerekenler ve Yaygın Hatalar

useRef güçlü bir araç olsa da, yanlış kullanıldığında beklenmedik davranışlara veya hatalara yol açabilir.

current Özelliğinin Mutasyonu

useRef tarafından döndürülen objenin current özelliğini doğrudan değiştirmek güvenlidir ve amaçlanan bir kullanımdır. Ancak, useRef'in kendisini (yani ref objesini) doğrudan değiştirmeye çalışmaktan kaçının.

Render Sırasında ref.current Değerini Okuma/Yazma

React'in render fazı saf olmalıdır, yani yan etkiler içermemelidir. ref.current değerini okumak veya yazmak, özellikle bu değer UI'nın render edilme şeklini etkiliyorsa, yan etki olarak kabul edilebilir. Bu tür işlemler genellikle useEffect hook'u içinde yapılmalıdır.


// KÖTÜ KULLANIM: Render sırasında yan etki
function BadComponent() {
  const myRef = useRef(0);
  myRef.current = myRef.current + 1; // Her render'da ref'i değiştiriyor
  // Bu beklenmedik davranışlara yol açabilir
  return 

Sayı: {myRef.current}

; } // İYİ KULLANIM: useEffect içinde yan etki function GoodComponent() { const myRef = useRef(0); useEffect(() => { myRef.current = myRef.current + 1; // Yan etki useEffect içinde }, []); // Sadece ilk render'da çalışır return

Sayı: {myRef.current}

; }

ref'leri Props Olarak Geçirme

Bir useRef objesini doğrudan bir alt bileşene ref prop'u olarak geçirmek, React'in ref yönetim sistemiyle çakışabilir. Eğer bir alt bileşenin DOM'una erişmek istiyorsanız, forwardRef API'sini kullanmanız gerekir.


// ChildComponent.js
import React, { forwardRef } from 'react';

const ChildComponent = forwardRef((props, ref) => {
  return ;
});

export default ChildComponent;

// ParentComponent.js
import React, { useRef } from 'react';
import ChildComponent from './ChildComponent';

function ParentComponent() {
  const inputRef = useRef(null);

  const handleClick = () => {
    inputRef.current.focus();
  };

  return (
    
); }

Sonuç

useRef hook'u, React'in deklaratif paradigması içinde imperatif operasyonlar gerçekleştirmek ve bileşen yaşam döngüsü boyunca mutable değerleri korumak için vazgeçilmez bir araçtır. Sadece DOM elementlerine erişimden çok daha fazlasını sunar; gereksiz yeniden render'ları önleyerek performansı artırır ve karmaşık state yönetimi senaryolarında useState'e güçlü bir alternatif sunar. useRef'in ne zaman ve neden kullanıldığını gerçekten anlamak, daha sağlam, verimli ve bakımı kolay React uygulamaları geliştirmenizi sağlayacaktır. Artık useRef'in sadece ne yaptığını değil, neden var olduğunu ve React ekosistemindeki stratejik önemini de biliyorsunuz.

SSS (Sık Sorulan Sorular)

useRef ile useState arasındaki temel fark nedir?

useState, UI'yı etkileyen ve değiştiğinde bileşenin yeniden render edilmesini tetikleyen durumları yönetmek için kullanılır. useRef ise, bileşenin yaşam döngüsü boyunca kalıcı olması gereken, ancak değiştiğinde yeniden render'ı tetiklemeyen mutable değerleri veya DOM referanslarını tutmak için kullanılır.

useRef ne zaman null olur?

useRef(null) ile başlatıldığında current özelliği başlangıçta null olur. Eğer bir DOM elementine bağlanmışsa, bileşen mount edildiğinde current özelliği ilgili DOM elementine işaret eder. Bileşen unmount edildiğinde ise current tekrar null olabilir (React tarafından otomatik olarak).

useRef ile oluşturulan değerler component'in her render'ında sıfırlanır mı?

Hayır, useRef ile oluşturulan değerler, current özelliği aracılığıyla bileşenin tüm yaşam döngüsü boyunca korunur ve her render'da sıfırlanmaz. Yalnızca bileşen ilk kez mount edildiğinde initialValue ile başlatılır.

useRef'i forwardRef ile nasıl kullanırım?

Bir üst bileşenden alt bileşenin DOM elementine veya bir React bileşenine ref geçirmek için forwardRef kullanılır. forwardRef, bir bileşenin ref'i bir alt bileşene "iletmesine" olanak tanır. Alt bileşen bu ref'i kendi içinde bir DOM elementine veya başka bir React bileşenine atayabilir.

Yorumlar
İçeriği beğendiniz mi? Bir tartışma başlatın veya görüşlerinizi paylaşın.
Yorum Yaz

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Gönder

E-posta Bülteni
Yazılım Topluluğuna Katılın
En son güncellemeleri, yaratıcı ipuçlarını ve özel kaynakları doğrudan e-posta kutunuza alın. Tasarım ve inovasyonun geleceğini birlikte keşfedelim.
Mobil sürümden çık