Türkçe

React useEvent hook'u ile dinamik uygulamalarda kararlı olay yöneticisi referansları oluşturun, performansı artırın ve gereksiz render'ları önleyin.

React useEvent: Kararlı Olay Yöneticisi Referansları Elde Etme

React geliştiricileri, özellikle dinamik bileşenler ve closure'lar içeren senaryolarda olay yöneticileriyle (event handlers) çalışırken sıklıkla zorluklarla karşılaşırlar. React ekosistemine nispeten yeni bir ekleme olan useEvent hook'u, bu sorunlara zarif bir çözüm sunarak geliştiricilerin gereksiz yeniden render'ları (re-renders) tetiklemeyen kararlı olay yöneticisi referansları oluşturmasına olanak tanır.

Sorunu Anlamak: Olay Yöneticilerinin Kararsızlığı

React'te, bileşenler prop'ları veya state'leri değiştiğinde yeniden render edilir. Bir olay yöneticisi fonksiyonu prop olarak iletildiğinde, genellikle üst bileşenin (parent component) her render işleminde yeni bir fonksiyon örneği oluşturulur. Bu yeni fonksiyon örneği, aynı mantığa sahip olsa bile, React tarafından farklı kabul edilir ve bu da onu alan alt bileşenin (child component) yeniden render edilmesine yol açar.

Bu basit örneği ele alalım:


import React, { useState } from 'react';

function ParentComponent() {
  const [count, setCount] = useState(0);

  const handleClick = () => {
    console.log('Üst Bileşenden Tıklandı:', count);
    setCount(count + 1);
  };

  return (
    

Sayı: {count}

); } function ChildComponent({ onClick }) { console.log('ChildComponent render edildi'); return ; } export default ParentComponent;

Bu örnekte, handleClick fonksiyonu ParentComponent'in her render işleminde yeniden oluşturulur. ChildComponent optimize edilmiş olsa bile (örneğin, React.memo kullanarak), onClick prop'u değiştiği için yine de yeniden render edilecektir. Bu durum, özellikle karmaşık uygulamalarda performans sorunlarına yol açabilir.

useEvent ile Tanışın: Çözüm

useEvent hook'u, olay yöneticisi fonksiyonuna kararlı bir referans sağlayarak bu sorunu çözer. Olay yöneticisini, üst bileşeninin yeniden render döngüsünden etkili bir şekilde ayırır.

useEvent, (React 18 itibarıyla) yerleşik bir React hook'u olmasa da, özel bir hook olarak kolayca uygulanabilir veya bazı framework ve kütüphanelerde yardımcı araç setinin bir parçası olarak sunulur. İşte yaygın bir uygulaması:


import { useCallback, useRef, useLayoutEffect } from 'react';

function useEvent any>(fn: T): T {
  const ref = useRef(fn);

  // useLayoutEffect, senkron güncellemeler için burada kritik öneme sahiptir
  useLayoutEffect(() => {
    ref.current = fn;
  });

  return useCallback(
    (...args: Parameters): ReturnType => {
      return ref.current(...args);
    },
    [] // Bağımlılık dizisi, kararlılığı sağlamak için kasıtlı olarak boştur
  ) as T;
}

export default useEvent;

Açıklama:

useEvent'in Pratikte Kullanımı

Şimdi, önceki örneği useEvent kullanarak yeniden düzenleyelim (refactor):


import React, { useState, useCallback, useRef, useLayoutEffect } from 'react';

function useEvent any>(fn: T): T {
  const ref = useRef(fn);

  // useLayoutEffect, senkron güncellemeler için burada kritik öneme sahiptir
  useLayoutEffect(() => {
    ref.current = fn;
  });

  return useCallback(
    (...args: Parameters): ReturnType => {
      return ref.current(...args);
    },
    [] // Bağımlılık dizisi, kararlılığı sağlamak için kasıtlı olarak boştur
  ) as T;
}

function ParentComponent() {
  const [count, setCount] = useState(0);

  const handleClick = useEvent(() => {
    console.log('Üst Bileşenden Tıklandı:', count);
    setCount(count + 1);
  });

  return (
    

Sayı: {count}

); } function ChildComponent({ onClick }) { console.log('ChildComponent render edildi'); return ; } export default ParentComponent;

handleClick fonksiyonunu useEvent ile sarmalayarak, count state'i değiştiğinde bile ChildComponent'in ParentComponent'in render'ları boyunca aynı fonksiyon referansını almasını sağlarız. Bu, ChildComponent'in gereksiz yere yeniden render edilmesini önler.

useEvent Kullanmanın Faydaları

useEvent için Kullanım Alanları

Alternatifler ve Dikkat Edilmesi Gerekenler

useEvent güçlü bir araç olsa da, akılda tutulması gereken alternatif yaklaşımlar ve hususlar vardır:

Uluslararasılaştırma ve Erişilebilirlik Hususları

Küresel bir kitle için React uygulamaları geliştirirken, uluslararasılaştırmayı (i18n) ve erişilebilirliği (a11y) göz önünde bulundurmak çok önemlidir. useEvent'in kendisi i18n veya a11y'yi doğrudan etkilemez, ancak yerelleştirilmiş içeriği veya erişilebilirlik özelliklerini yöneten bileşenlerin performansını dolaylı olarak iyileştirebilir.

Örneğin, bir bileşen mevcut dile göre yerelleştirilmiş metin gösteriyorsa veya ARIA nitelikleri kullanıyorsa, bu bileşen içindeki olay yöneticilerinin kararlı olmasını sağlamak, dil değiştiğinde gereksiz yeniden render'ları önleyebilir.

Örnek: Yerelleştirme ile useEvent Kullanımı


import React, { useState, useContext, createContext, useCallback, useRef, useLayoutEffect } from 'react';

function useEvent any>(fn: T): T {
  const ref = useRef(fn);

  // useLayoutEffect, senkron güncellemeler için burada kritik öneme sahiptir
  useLayoutEffect(() => {
    ref.current = fn;
  });

  return useCallback(
    (...args: Parameters): ReturnType => {
      return ref.current(...args);
    },
    [] // Bağımlılık dizisi, kararlılığı sağlamak için kasıtlı olarak boştur
  ) as T;
}

const LanguageContext = createContext('en');

function LocalizedButton() {
  const language = useContext(LanguageContext);
  const [text, setText] = useState(getLocalizedText(language));

  const handleClick = useEvent(() => {
    console.log('Düğmeye tıklandı, dil:', language);
    // Dile göre bir eylem gerçekleştir
  });

  function getLocalizedText(lang) {
      switch (lang) {
        case 'en':
          return 'Click me';
        case 'fr':
          return 'Cliquez ici';
        case 'es':
          return 'Haz clic aquí';
        default:
          return 'Click me';
      }
    }

    // Dil değişimini simüle et
    React.useEffect(()=>{
        setTimeout(()=>{
            setText(getLocalizedText(language === 'en' ? 'fr' : 'en'))
        }, 2000)
    }, [language])

  return ;
}

function App() {
  const [language, setLanguage] = useState('en');

  const toggleLanguage = useCallback(() => {
    setLanguage(language === 'en' ? 'fr' : 'en');
  }, [language]);

  return (
    
      
); } export default App;

Bu örnekte, LocalizedButton bileşeni mevcut dile göre metin görüntüler. handleClick yöneticisi için useEvent kullanarak, dil değiştiğinde düğmenin gereksiz yere yeniden render edilmemesini sağlarız, bu da performansı ve kullanıcı deneyimini iyileştirir.

Sonuç

useEvent hook'u, performansı optimize etmek ve bileşen mantığını basitleştirmek isteyen React geliştiricileri için değerli bir araçtır. Kararlı olay yöneticisi referansları sağlayarak gereksiz yeniden render'ları önler, kod okunabilirliğini artırır ve React uygulamalarının genel verimliliğini yükseltir. Yerleşik bir React hook'u olmasa da, basit uygulaması ve önemli faydaları onu her React geliştiricisinin araç setine eklemeye değer kılar.

useEvent'in arkasındaki prensipleri ve kullanım alanlarını anlayarak, geliştiriciler küresel bir kitle için daha performanslı, bakımı kolay ve ölçeklenebilir React uygulamaları oluşturabilirler. Optimizasyon tekniklerini uygulamadan önce daima performansı ölçmeyi ve uygulamanızın özel ihtiyaçlarını göz önünde bulundurmayı unutmayın.