React Memo ile Performans Artırma

React JS Memo İle Performans Optimizasyonu Nasıl Yapılır?

Hızın önemli olduğu bir zamandayız. Aslında belkide her zaman hız önemliydi. Fakat şuan oldukça önemli. Bir sayfa üzerinde işlem yaparken oluşacak en küçük gecikme kullanıcı deneyimini olumsuz etkiliyor. Bu nedenle tasarım ve geliştirme aşamasında uygulama performansını geliştirmek oldukça önemli.

Bu Bölümde Öğreneceklerimiz

Bu yazı bittiği zaman aşağıdaki konular hakkında fikir sahibi olacaksınız.

  • Gereksi re-render işlemi nedir ve nasıl baş edilir?
  • React memo nedir ve nasıl kullanılır?
  • React memo nasıl özelleştirirlir?
  • React memo ne zaman kullanılmalıdır?
  • React memo nerelerde kullanılmamalıdır?

React Memo Nedir ve Neden Kullanılır?

React JS ile uygulama geliştirirken, UI bileşenleri ön plana çıkıyor. React bize arayüzün daha az kaynak tüketmesi için Virtual DOMu sunuyor. Bu bizim sayfanın en küçük elemanına dokumamızı kolaylaştırırken, sayfa içerisinde oluşan bir değişikliği sunarken, sadece değişikliğin olduğu yeri re-render edilmesini de sağlıyor. Bu ne demek, mesela sayfanın içerisinde skor bilgisinin tutulduğu bir komponent olsun, skor bilgisi değiştiğinde sadece bu komponent re-reder edilecek ve buda bize günün sonunda daha hızlı bir arayüz ve daha az bir maliyet olarak geri dönecektir.

React JS Komponentlerinde Gereksiz Re-Render İşlemleri

Peki her zaman bu böyle oluyor mu? Yoksa bazen bizim isteğimizin dışında gereksiz render yapılıyor mu? Şimdi bunu inceleyerek kaldığımız noktaya geri dönelim.

Bunun için klasik bir uygulama olan sayaç uygulamasını kullanacağız, bir buton tanımlayacağız ve butona tıkladığımızda ekrandaki sayıyı artıracağız.

Uygulamamızı npx create-react-app ile oluşturuyoruz. Siz de buna göre kodları yorumlayabilirsiniz. Uygulamamızda bir Header komponenti oluşturacağız.

Header komponenti sadece bir başlık sunacak ve başka bir işlevi olmayacak.

import React from 'react';

function Header() {
    console.log("The Header component re-rendered.")
    return (
        <div>
            <h1>Simple Counter</h1>
        </div>
    );
}

export const Header;

Şimdi App komponentimizi hazırlayalım.


import './App.css';
import React from 'react';
import Header from './Header';

function App() {
    const [counter, setCounter] = useState(0);

    const handleClick = (e) => {
        e.preventDefault();
        setCounter(counter++);
    }

    return (
        <div className='App'>
            <Header />
            <h3>Current Counter : {counter}</h3>
            <button onClick={(e) => handleClick(e)}>Count</button>
        </div>
    )
}

export default App;

Artık uygulamamızı başlatabiliriz. Uygulamamızın normal bir şekilde çalıştığını görebilirsiz. Peki görmemiz gereken sorun nedir? Şimdi javascript konsolunu açalım, ve sonrasında Count butonuna tıklayarak sayacın bir artmasını sağlayalım ve aynı anda javascript konsoluna da bakalım. Gördüğünüz gibi konsola

The Header component re-rendered.

yazdırıldı. Neden? Çünkü bir komponent re-render edildiğinde içerisindeki tüm komponentler de yeniden render edilecektir. App komponentinin içeriği Count butonuna tıklandığında değişti, o zaman React App komponenti içerisindeki tüm verileri ve dolayısı ile içeridiği tüm komponentleri de yeniden render edecektir. Buda bir performans kaybına neden olabilecektir.

React Memo İle Memoritation / Hafızaya Alma

Yukarıdaki örnekte ciddi bir performans kaybı yok bu nedenle bir sorun teşkil etmeyebilir, fakat çok daha fazla işlemin yapıldığı bir komponente gereksiz re-render işlemleri bir performans sorununa neden olabilir. Bunu engellemek için React bize memo metodunu sunuyor. React memo ile bir komponenti sarmaladığımız zaman React ilk render yapıldığında o komponenti oluşturur ve hafızaya alır. Sonra gerektiğinde bu hafızadaki kopyasını kullanır. Bunun yaparkende props değişikliği var mı denetler.

React memo hafızaya aldığı kopyayı props kontrolü yaparak kullanır, mesela bir hesaplama için prop olarak fiyat bilgisini 1055 olarak girdik. React memo bu prop bilgisine göre sonucu hafızaya alır ve fiyat propunun değeri 1055 olduğu sürece tekrar hesaplama yapmaz ve hafızadaki kopyayı kullanır. Eğer prop değeri değişirse mesela 955 olursa bu değere göre bir hesaplama yapar ve o şekilde hafızaya alır. Böylece de aynı değerler geldiğinde yeniden bir işlem yapılmayacağı için bir performans artışı gözlemlenir.

React memo komponentin yeniden re-render edilmeyeceğini garanti etmez, çünkü asıl hedef performans artışıdır. Bunu bilerek işleminizi yapmalısınız.

React memo kullanırken dikkat etmemiz gereken bazı noktalar var, hafızaya alma bir maliyettir, yeniden render etmek de bir maliyettir. Sonuçta bunlardan hangisini seçmeliyiz? Bunun kararını uygulamamız çalıştığında test ederek verebiliriz.

Gereksiz yere hafızaya almaktan kaçınmalıyız, çünkü bu da bir maliyettir. Basit komponentlerde React memo kullanmak yerine daha etkin yöntemler denenebilir.

React memo sadece privative değişken değerlerine sahip proplarda kullanılabilir. Nesne ve fonksiyon alan proplarda bir etkisi yoktur.

Memo özelliği ile önbelleklenen / hafızaya alınan komponetlerde state, context ve prop değişikliği olduğunda re-render işlemi yapılacaktır. Bu konuya dikkat etmek önemlidir.

React Memo ile Sayaç Örneği

Şimdi yukarıda yaptığımız sayacı React memo ile tekrar tasarlayalım ve sonucunu görelim.

Uygulamamızda sadece kullanacağımız React memo metodu farklı olacaktır. Diğer yerler aynı şekilde kalacaktır.

import React, { memo } from 'react';

function Header() {
    console.log("The Header component re-rendered.")
    return (
        <div>
            <h1>Simple Counter</h1>
        </div>
    );
}

export const memo(Header);

Şimdi App komponentimizi hazırlayalım.


import './App.css';
import React from 'react';
import Header from './Header';

function App() {
    const [counter, setCounter] = useState(0);

    const handleClick = (e) => {
        e.preventDefault();
        setCounter(counter+1);
    }

    return (
        <div className='App'>
            <Header />
            <h3>Current Counter : {counter}</h3>
            <button onClick={(e) => handleClick(e)}>Count</button>
        </div>
    )
}

export default App;

Gördüğünüz gibi memo özelliğini kullanmak için sadece Header komponentini export ederken memo ile sarmaladık. Yapmamız gereken sadece bu. Şimdi uygulamamızı çalıştırdığımızda, ilk render edildiğinde Header komponenti hafızaya alınacak ve konsoldan The Header component re-rendered. yazacak ve sayaç artırıldığında ise hafızadan Header komponenti okunacağı ve yeniden render eldilmeyeceği için sadece sayaç artacaktır.

React JS Memo Kullanımı
React JS Memo Kullanımı

React Mome Kullanım Şekilleri

React memoyu bir kaç farklı şekilde kullanabiliriz.

  • Önce React memo fonksiyonunu import ederiz. Sonrasında komponenti export ederken memo ile sarmalarız.
import { memo } from 'react';
...
...
...

export const memo(HafizayaAlinacakKomponent);

  • React memo import edilir ve komponent komple memo içerisinde yazılır.
import { memo } from 'react';

const Komponent = () React.memo(() => {
    ...
});

export const Komponent;

  • Komponent export edilirken React.memo ile sarmalanır.

...
...
...

export const React.memo(Komponent);

React Memo İle Kendi İsteğimize Göre Hafızaya Alma

React memo kendi içerisinde tutarlı bir şekilde çalışıyor. Fakat eğer proplardan bir tanesi basit değişken değilde bir nesne ise, nesne üzerindeki değişikliği fark edemeyecek ve normal çalışmayacaktır. React memo bu durumlar için farklı bir çözüm sunuyor. Kendi fonksiyonumuzu yazma. Evet proplarda bir değişiklik olup olmadığını kendi yazacağımız bir fonksiyon ile kendimiz bulabiliriz. Bu bize daha etkili bir memorizasyon işlemi sunacaktır. Peki bunu nasıl yapabiliriz?

Memo metoduna ikinci bir parametre olarak vereceğimiz callback fonksiyonu ile kendi şartlarımızı oluşturarak daha etkin bir şekilde hafızalama / önbellekleme işini yapabiliriz.

Gelin sayaç uygulamamıza geri dönelim ve şöyle bir şart koşalım, eğer sayaç 5 ile 10 arasında ise hafızaya alsın, diğer durumlarda hafızaya almasın. Şimdi bunu yapmak için önce bir callback fonksiyonu yazacağız, bu fonksiyona areEqual ismini verelim. Siz dilediğiniz ismi verebilirsiniz.

Öncelikle bilmemiz gereken bu fonksiyon true veya false değerini geri dönecektir. Eğer true dönerse yeniden render yapılmayacak, fakat false dönerse re-render işlemi yapılacaktır. Mantığımızı buna göre kuralım. Farkı görmemiz için counter değişkenini Header komponentine bir prop olarak vereceğiz. Sonrasına sayacı artırtıkça değişimi hep beraber göreceğiz.


import './App.css';
import React, {useState} from 'react';
import Header from './components/Header';

function App() {
  const [counter, setCounter] = useState(0);

  const handleClick = (e, direction) => {
    e.preventDefault();
    direction ? setCounter(counter+1) : setCounter(counter-1);
  }

  return (
    <div className="App">
      <Header counter={counter} />

      <hr />

      <h3>Current Counter : {counter}</h3>
      <button onClick={(e) => handleClick(e, false)}>Count -</button>
      <button style={{marginLeft: '9px'}} onClick={(e) => handleClick(e, true)}>Count +</button>

    </div>
  );
}

export default App;

Şimdi uygulamamızı çalıştırıp sonuca bakalım. Uygulama çalıştığında Heade komponetinde de sayacı göreceğiz bir farkla, biz butona tıklayıp sayacı 5 yapana kadar Header komponenti yeniden render edilecek, 5 – 10 arasında iken yeniden render edilmeyecek, counter 10 dan büyük olduğunda ise tekrar butona her tıkladığımızda render edilecektir.

React JS Memo Kullanımı
React JS Memo Kullanımı

Son Sözler

Hız ve performans günümüzde vaz geçilmez ikilidir. Bu nedenle yaptığımız geliştirmelerde bu iki özelliğe fazladan dikkat etmemiz gerekiyor. Eğer yazıdğımız uygulama yavaşsa veya bazı yerlerde performans kaybı yaşıyorsa kullanıcılar bundan çokda memnun olmayacaklardır. Bu bize müşteri ve iş kaybı olarak geri dönecektir.

React JS ile geliştirme yaparken performansı artırmak için React ile bize sunulan memo özelliğini doğru bir şekilde kullanmak bize performans artışı olarak geri dönecektir. React memo performans artışı için geliştirilmiştir. Kullanıldığında re-render işleminin yapılmayacağını garanti etmez.

Uygulamayı geliştirdikten sonra eğer performans sorunları gözlüyorsak bu durumda uygun gördüğümüz yerlerde React memo özelliğinden faydalanabiliriz. React JS ve JavaScript ile ilgili yeni yazılarda buluşmak üzere.

Sizin de eklemek istedikleriniz veya sormak istedikleriniz varsa yorum bölümünden yazabilirsiniz.

Yorum bırakın

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