What are useCallBack, useMemo and useEffect? How to and When use? What are the difference?

Reactjs hooklarından useCallback, useEffect ve useMemo hookları zaman zaman birbiriyle karışan hookslardır. Bu üç hooksun nasıl çalıştığını ve ne zaman kullanılacağını inceleyeceğiz.

useEffect

useEffect Component içindeki state, props gibi varlıklar render olduktan sonra tetiklenen bir fonksiyondur. Bu tetiklenmeyi bir dizi içindeki verilen varlıklara göre yapar.

En basit kullanımı aşağıdaki şekildedir. Counter state’i her değişim sonrası tetiklenecektir. Önceki değeriyle yeni değeri aynı ise render olmayacaktır.

Depedency array içine fonksiyon eklenmesi durumunda o fonksiyonun her çağrılmasında tetiklenir.

Array boş olması durumunda bağlı olduğu component render olduktan sonra tetiklenir. Önce return içindekiler render olur daha sonra useEffect.

Yukarıda verdiğimiz örneklerde hep mount işlemleri yaptık yani değişimi yakala ve çalıştır. Peki çalıştırma bittikten sonra tetiklemek istersek ne yapmalıyız (unmount)?

return () => counter değeri güncellemeden önce handle eden kısım. Genellikle window.addEventListener ve timerlarda uygulanan bir davranıştır.

Bu örnekte counter her değiştiğinde window’a keyup eventi için bir fonksiyon ekliyoruz. Eğer unmount ile remove yapmasaydık her useEffect içine girişte keyup için event ekleyecekti. Örneğin 5 kez counter değiştiyse keyup için 5 tane handler olacaktı. Böylece bir keyup yaptığımızda keyupHandler 5 kez tetiklenecektir.

useCallback

Ana componenet her render olduğunda içindeki fonksiyonların bir instance yeniden oluşturulur, useCallback gereksiz yere oluşturulmasını engeller ve fonskiyonu memoize eder. useEffect gibi bir bağımlı dizisine sahiptir, objeler belirlenip sadece bu objeler değiştiğinden yeniden oluşturulacak şekilde çalışır.

Yukarıdaki örnekte uygulama ilk render olduğunda fonksiyonu memoize eder, yani list ve counter değerleri değişse bile eski değerleri ile arama yapar. Eğer memoize etmeseydik her seferinde function yeniden oluşturacaktı. Ama bu yukarıdaki örnekte listeye bir değer eklense bile fonksiyonda hâlâ eski liste göre arama yapacaktır bunu düzeltmek için bağımlılık dizesine listi eklemeliyiz.

Eğer ki büyük bir list var ise yukarıdaki bir mantıkta fonksiyonu memoize etmek gayet mantıklı, eğer maliyeti yüksek olmayan bir fonksiyonunuz var ise gereksiz yük olur. memoize etmemenin de kendine göre bir maliyeti var ve bazen organizasyonu zor olabiliyor.

useMemo

useMemo’nun çok detaylı açıklanmış bir örnek yazısını bakabilirsiniz. What are React Memo and useMemo? What situations is it used?

useMemo hooksu useCallback fonksiyonu gibi bir memoize işlemi yapar ama sadece fonksiyonu memoize etmez, bir girdiye göre çıkan sonucu hesaplar ve onu memoize eder.

Örneğin faktöriyel hesaplayan bir metodumuz var. Girdimiz 5 ise 120 çıkış olur ve bunu hafızaya atar. Siz tekrar 5’in faktöriyelini hesapladığınız zaman yeniden hesaplamaz ve direkt 120’yi döner. Bu örnekler çoğaltılabilir örneğin +4k sabit bir liste üzerinde sıralama yapıyorsunuz. Bu sıralama’da iki tür olabilir artan ya da azalan. Listi cache’e atar ve bağımlılıkları değişmedikçe yeniden hesaplama yapmaz.

Yukarıdaki örnek gereksiz bir kullanımdır. Zaten isIncrement değeri aynı kaldıkça useEffect tetiklenmeyecektir.

Bu yazılan örnek daha kullanışlı sort + ‘ya art arta tıklamada gereksiz bir render olmaz. Sadece isIncrement verisi değiştikçe fonksyion yeniden sorting yapar.

Ne zaman kullanmalıyız? (useMemo ve useCallback)

Öncelikle uygulamanızı tasarlarken bu performans hooksları kullanılmamalı. Bu hookslar gerçekten ihtiyaç olan yerde kullanılmalısınız. Performans geliştirme aynı zamanda bazı sorumlulukları da peşinde getirir, bu geliştirmeler bedavaya yapılmaz. Diyelim her fonksiyonunuzu useCallback ile memoize ettik bu durumda bırakın performans geliştirmeyi daha da performansı düşürmüş oluruz. Component içinde inline fonksiyonların yeniden oluşması maliyetli bir işlem değildir, yeniden fonksiyonu oluşturduğunda garbage collector eskisini çöpe atar ama useCallback ile memoize edilirse çalışmaz ve memory birikir.
Peki hangi durumlarda kullanmalıyız?

  • Referans karşılaştırmaları
  • Maliyetli işlemler

Yukarıdaki örneğe baktığımızda obj1 ve obj2 eşit olmasına rağmen false döner. (derinlere girmiyorum şimdilik)
Bu noktada dependecy list bu açığı kapatıyor ve yapması gereken işi yapıyor. Veriler değiştiğinde eğer biz manuel olarak kontrol etseydik referans tipler için sonuç hep false çıkacağından her seferinde render olacaktır işte bu karşılaştırma işini react’a bırakıyoruz. Şimdi gereksiz render’ın doğru bir şekilde önüne nasıl geçilir bakalım.

Yukarıdaki örnekte eğer fonksiyon ve diziyi memoize etmeseydik counter her değiştiğinde ya da ana component render olduğunda yeni bir list ve getItem fonksiyonlarını oluşturacaktır. Yukarıdakine benzer durumlarda kullanmanızda bir sakınca yok. Ama kullanırken gerçekten ihtiyacınız olup olmadığını iyice analiz ediniz.

Gönderinin sonuna geldik başka bir makalede görüşmek üzere 🙂

You may also like...

1 Response

  1. Muhammed İlan says:

    Çok işime yaradı çok teşekkür ederim

Leave a Reply

Your email address will not be published.

English