memo

memo, bileşenin prop’ları değişmediğinde yeniden render edilmesini önlemenize izin verir.

const MemoizedComponent = memo(SomeComponent, arePropsEqual?)

Not

React Compiler automatically applies the equivalent of memo to all components, reducing the need for manual memoization. You can use the compiler to handle component memoization automatically.


Referans

memo(Component, arePropsEqual?)

Bir bileşenin önbelleğe alınmış (memoized) versiyonunu edinmek için ilgili bileşeni memo’ya sarmalayın. Bileşeninizin önbelleğe alınmış olan bu versiyon, üst bileşen render olsa dahi prop’ları değişmediği sürece genellikle yeniden render edilmez. Genellikle demenin sebebi React’ın yine de render edebilmesidir: önbelleğe alma (memoization) render’ı engellemenin garantisi değil, performans optimizasyonudur.

import { memo } from 'react';

const SomeComponent = memo(function SomeComponent(props) {
// ...
});

Daha fazla örnek için aşağıya bakınız.

Parametreler

  • Component: Önbelleğe almak istediğiniz bileşendir. memo bileşenin kendisini değiştirmez, önbelleğe alınmış yeni bir bileşen döndürür. Fonksiyon ve forwardRef dahil olmak üzere geçerli bir React bileşenini kabul eder.

  • isteğe bağlı arePropsEqual: Bileşenin eski ve yeni prop’ları olmak üzere iki argüman kabul eden ve değişiklik olup olmadığını kontrol eden fonksiyondur. Eski ve yeni değerler aynıysa, bileşen yeni prop’lar ile eski prop’lardakiyle aynı çıktıyı üretecekse, true döndürmelidir. Aksi takdirde false döndürmelidir. Çoğu zaman bu fonksiyonu belirtmezsiniz. Varsayılan olarak React, karşılaştırırken Object.is kullanır.

Dönüş değeri

memo, yeni bir React bileşeni döndürür. Bu bileşen memo’ya verilen bileşenle aynı davranır ancak üst bileşen render edildiğinde kendi prop’ları değişmemişse yeniden render edilmez.


Kullanım

Prop’lar değişmediğinde yeniden render’ı önlemek

React, normalde üst bileşen yeniden render edildiğinde altındaki bileşenleri de render eder. memo ile birlikte yeni prop’lar eskisiyle aynı olduğu sürece render edilmeyecek bileşenler oluşturabilirsiniz. Bu bileşenler, önbelleğe alınmış olarak nitelendirilir.

Bir bileşeni önbelleğe almak için, memo’ya sarmalayın ve döndürdüğü değeri orjinal bileşeninizin yerine kullanın:

const Greeting = memo(function Greeting({ name }) {
return <h1>Merhaba, {name}!</h1>;
});

export default Greeting;

React bileşeni her zaman saf (pure) render mantığına sahip olmalıdır. Yani prop’u, state’i ve context’i değişmediği sürece aynı çıktıyı vermesi beklenir. memo kullanarak React’a bu gerekliliğe uymasını söylersiniz. Prop’ları değişmediği takdirde React’ın render tetiklemesine gerek yoktur. Bileşenin state’i ya da context’i değişirse memo ile sarılmış olsa bile yeniden render olur.

Bu örnekte, Greeting bileşenin name değiştiğinde yeniden render olduğuna (çünkü prop’larından biridir), ancak address değiştiğinde olmadığına dikkat edin (çünkü Greeting’in prop’u değildir):

import { memo, useState } from 'react';

export default function MyApp() {
  const [name, setName] = useState('');
  const [address, setAddress] = useState('');
  return (
    <>
      <label>
        İsim{': '}
        <input value={name} onChange={e => setName(e.target.value)} />
      </label>
      <label>
        Adres{': '}
        <input value={address} onChange={e => setAddress(e.target.value)} />
      </label>
      <Greeting name={name} />
    </>
  );
}

const Greeting = memo(function Greeting({ name }) {
  console.log("Greeting'in render edildi:", new Date().toLocaleTimeString());
  return <h3>Merhaba{name && ', '}{name}!</h3>;
});

Not

memo’ya yalnızca performans optimizasyonu olarak bakmalısınız. Kodunuz onsuz çalışmıyorsa, öncelikle temel problemi bulun ve çözün. Ardından, performansı iyileştirmek için memo ekleyebilirsiniz.

Derinlemesine İnceleme

Bulduğunuz her yere memo eklemeli misiniz?

Uygulamanız bu site gibi ise ve etkileşimlerin çoğu kaba ise (bir sayfayı veya tüm bir bölümü değiştirmek gibi), memoizasyon genellikle gereksizdir. Öte yandan, uygulamanız daha çok bir çizim düzenleyicisi gibiyse ve etkileşimlerin çoğu ayrıntılı ise (şekilleri taşımak gibi), memoizasyon çok yararlı olabilir.

memo ile yapılan optimizasyon, yalnızca bileşeniniz sıkça aynı prop’larla yeniden render oluyorsa ve render mantığı pahallıysa değerlidir. Bileşeniniz yeniden render edildiğinde fark edilebilir bir gecikme yoksa önbelleğe almak gereksizdir. Bileşene her seferinde farklı prop (render esnasında tanımlanan fonksiyon veya nesne gibi) geçiyorsanız, memo tamamen gereksizdir. Bu nedenle memo ile birlikte genellikle useMemo ve useCallback’e ihtiyacınız olacaktır.

Diğer durumlarda bileşeni memo ile sarmalamanın faydası yoktur ancak önemli bir zararı da yoktur. Bu yüzden bazı ekipler üzerinde çok düşünmeden mümkün olduğunca önbelleğe almayı tercih ederler. Bu yaklaşımın dezavantajı, kodun daha az okunabilir hale gelmesidir. Ayrıca tüm önbelleğe alma işlemleri etkili değildir: “her zaman farklı” olan tek bir değer tüm bileşenin önbelleğe alınmasını engellemeye yeterlidir.

Pratikte birkaç prensibi takip ederek çoğu önbelleğe alma işlemini gereksiz hale getirebilirsiniz:

  1. Bir bileşen diğer bileşenleri görsel olarak sarmalıyorsa, JSX’i alt eleman olarak kabul etmesine izin verin. Böylece sarmalayan bileşenin kendi state’i güncellendiğinde, React alt bileşenlerin yeniden render edilmesinin gerekli olmadığını bilir.
  2. Mümkün olduğunca yerel state kullanın ve state’i gerektiğinden fazla yukarıya taşımayın. Örneğin, form gibi geçici state’leri veya fareyle bir öğenin üzerine gelindiği bilgisini ağacınızın en üstünde ya da global state kütüphanenizde tutmayın.
  3. Render mantığınızı saf tutun. Bileşeninizin render edilmesi bir soruna neden oluyorsa veya belirgin görsel farklılık oluşturuyorsa, bileşeninizde bir bug vardır! Önbelleğe almak yerine bug’ı çözün.
  4. State güncelleyen gereksiz efektlerden kaçının. React’ uygulamalarındaki çoğu performans sorunu, bileşenlerinizin defalarca render olmasına neden olan efekt zincirlerinden kaynaklanır.
  5. Efektlerinizden gereksiz bağımlılıkları kaldırmayı deneyin. Örneğin, efekt içerisindeki bazı nesne ve fonksiyonları bileşen dışarısına çıkarmak ön belleğe almaktan daha basittir.

Eğer spesifik bir etkileşim hala gecikmeli geliyorsa, React Developer Tools’un profiler’ını kullanarak önbelleğe alındığında fayda sağlayacak bileşenleri belirleyin ve tespit ettiklerinizi önbelleğe alın. Bu prensipler bileşenlerinizde hataların ayıklanmasını ve farkedilmesini kolaylaştırır. Bu nedenle durum farketmeksizin adımları takip etmekte yarar vardır. Gelecekte bunu herkes için kökten çözmek adına önbelleğe almayı nasıl otomatik hale getirebileceğimizi araştırıyoruz.


Ön belleğe alınmış (memoized) bileşeni state kullanarak güncelleme

Bir bileşen önbelleğe alınmış olsa bile kendi state’leri değiştiğinde yeniden render edilecektir. Önbelleğe almak, yalnızca bileşene üst bileşenden iletilen prop’larla ilgilidir.

import { memo, useState } from 'react';

export default function MyApp() {
  const [name, setName] = useState('');
  const [address, setAddress] = useState('');
  return (
    <>