Magento 2 Experten — Hyvä Theme, Tailwind CSS & SEO aus einer Hand ›

React.memo vertieft

React.memo vertieft

~15 Min. Lesezeit Zuletzt aktualisiert am 8. August 2026

"React für Einsteiger" hat useMemo/useCallback eingeführt – Werte bzw. Funktionen zwischenspeichern. React.memo ist ihr Gegenstück auf Komponenten-Ebene: eine ganze Komponente wird nur dann neu gerendert, wenn sich ihre Props TATSÄCHLICH geändert haben.

Das Grundproblem: Eltern-Render zieht Kind-Render nach sich

Standardverhalten in React, OHNE React.memo: Rendert eine Elternkomponente neu, rendern ALLE ihre Kindkomponenten ebenfalls neu – UNABHÄNGIG davon, ob sich deren Props geändert haben. Das ist meist harmlos (Re-Rendern ist billig), kann aber bei teuren Berechnungen innerhalb einer Kindkomponente oder bei sehr vielen Kindkomponenten (siehe nächstes Kapitel: Listen-Virtualisierung) spürbar werden.

React.memo anwenden: ProductCard einpacken

ProductCard ist ein perfektes Beispiel: ProductListPage rendert bei JEDER Sucheingabe (query-State-Änderung) neu – und damit bisher auch JEDE einzelne ProductCard, selbst wenn deren eigene Props (name, price, ...) unverändert bleiben:

src/components/ProductCard.jsx
import { memo, useState } from 'react';

function ProductCard({ name, price, imageUrl, onSelect, onAddToCart }) {
  const [isFavorite, setIsFavorite] = useState(false);

  function handleFavoriteClick(event) {
    event.stopPropagation();
    setIsFavorite(!isFavorite);
  }

  function handleAddToCartClick(event) {
    event.stopPropagation();
    onAddToCart();
  }

  return (
    <div className="product-card" onClick={onSelect}>
      <img src={imageUrl} alt={name} className="product-card__image" />
      <div className="product-card__info">
        <h3 className="product-card__name">{name}</h3>
        <p className="product-card__price">${price.toFixed(2)}</p>
      </div>
      <button className="product-card__favorite" onClick={handleFavoriteClick}>
        {isFavorite ? '♥' : '♡'}
      </button>
      <button className="product-card__add-to-cart" onClick={handleAddToCartClick}>
        In den Warenkorb
      </button>
    </div>
  );
}

export default memo(ProductCard);

Nur eine Änderung zählt: export default memo(ProductCard) statt export default ProductCard. Von jetzt an vergleicht React vor jedem Re-Render ALLE Props von ProductCard per flachem Vergleich (Object.is auf JEDEN einzelnen Prop-Wert) mit dem vorherigen Aufruf – sind sie IDENTISCH, wird der Render komplett übersprungen.

Die häufigste Falle: Inline-Funktionen als Props

Jetzt kommt der Haken, der React.memo für viele Einsteiger zur Enttäuschung macht: Sehen Sie sich ProductListPage.jsx an – dort wird onAddToCart={{() => dispatch(addItem(...))}} als Inline-Arrow-Function übergeben. Bei JEDEM Render von ProductListPage entsteht eine NEUE Funktion – auch wenn ihr Inhalt identisch aussieht, ist es für Object.is eine ANDERE Referenz. React.memo sieht also "onAddToCart hat sich geändert" und rendert trotzdem neu – memo allein hätte hier praktisch NICHTS gebracht.

Die Lösung: onAddToCart mit useCallback stabilisieren

Um React.memo wirksam zu machen, muss die übergebene Funktion selbst über Render-Durchläufe hinweg STABIL bleiben – genau das leistet useCallback aus "React für Einsteiger" Kapitel 10. Hier der relevante Ausschnitt aus ProductListPage.jsx, mit useCallback ergänzt (der Rest der Datei bleibt wie in Kapitel 29 gezeigt):

import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
// ... übrige Imports unverändert

// ... innerhalb der Komponente, NACH dem useDispatch():
const handleAddToCart = useCallback(
  (product) => dispatch(addItem({ sku: product.sku, name: product.name, price: product.price })),
  [dispatch]
);

// ... im JSX:
<ProductCard
  key={product.sku}
  name={product.name}
  price={product.price}
  imageUrl={product.imageUrl}
  onSelect={() => navigate(`/products/${product.sku}`)}
  onAddToCart={() => handleAddToCart(product)}
/>

Achtung: Aufgepasst: onAddToCart={{() => handleAddToCart(product)}} ist IMMER NOCH eine neue Inline-Funktion pro Render, weil sie product aus dem Closure einfängt! useCallback stabilisiert nur handleAddToCart SELBST (die Funktion, die einen product-Parameter entgegennimmt), nicht die pro-Produkt spezifische Inline-Version davon. Um DIESES Problem vollständig zu lösen, bräuchte ProductCard selbst sku/product als Prop und würde onAddToCart(product) intern mit dem eigenen sku aufrufen – eine Umstrukturierung, die den Rahmen dieses Kapitels sprengen würde. Der Kernpunkt hier: React.memo zu verstehen bedeutet auch zu verstehen, wie LEICHT man es versehentlich wirkungslos macht.

Wann sich React.memo überhaupt lohnt

  • Die Komponente rendert TEUER (komplexe Berechnung, großer DOM-Baum, viele Kinder) UND
  • sie bekommt HÄUFIG dieselben Props erneut (z. B. weil ihr Elternteil aus einem anderen Grund oft neu rendert) UND
  • ihre Props sind tatsächlich REFERENZ-STABIL zu halten (primitives wie Zahlen/Strings sind das automatisch; Objekte/Arrays/Funktionen brauchen useMemo/useCallback).

Achtung: React.memo ist NICHT kostenlos – der Props-Vergleich selbst kostet Zeit. Bei kleinen, billig zu rendernden Komponenten mit oft wechselnden Props kann React.memo die App sogar LANGSAMER machen (Vergleichskosten > eingesparte Renderkosten). Verwenden Sie den Profiler aus dem letzten Kapitel, um VOR und NACH dem Hinzufügen von memo zu messen, statt es blind überall einzusetzen.

Bonus: eine eigene Vergleichsfunktion

memo() akzeptiert optional ein zweites Argument – eine eigene Vergleichsfunktion, falls der Standard-Flachvergleich nicht passt (z. B. wenn ein Prop ein Array ist, dessen INHALT, nicht dessen Referenz, verglichen werden soll):

export default memo(ProductCard, (prevProps, nextProps) => {
  // true zurückgeben = "gleich, NICHT neu rendern"
  return prevProps.name === nextProps.name && prevProps.price === nextProps.price;
});

Tipp: Faustregel: memo() ohne zweites Argument reicht für 95% der Fälle. Eine eigene Vergleichsfunktion ist ein Werkzeug für seltene Sonderfälle, nicht der Standardweg – sie ist selbst eine potenzielle Fehlerquelle (vergisst man einen Prop im Vergleich, kann ein echtes Update fälschlich übersprungen werden).