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

useMemo und useCallback in React verstehen

useMemo und useCallback

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

Diese beiden Hooks gehören zusammen: Beide "merken sich" (memoisieren) etwas zwischen Render-Durchläufen, um unnötige, wiederholte Arbeit zu vermeiden. useMemo merkt sich einen berechneten WERT, useCallback merkt sich eine FUNKTION.

Das Grundproblem: jede State-Änderung rendert die ganze Funktion neu

Wichtig zu verstehen: Bei JEDER State-Änderung führt React die komplette Komponentenfunktion erneut aus – nicht nur den Teil, der sich sichtbar ändert. Das bedeutet: JEDE Variable, JEDE Berechnung und JEDE Funktion innerhalb der Komponente wird bei jedem Rendern neu erzeugt. Für einfache Berechnungen (const summe = a + b) ist das völlig unproblematisch – Millionen davon pro Sekunde sind kein Problem. Bei WIRKLICH teuren Berechnungen (große Listen sortieren, komplexe Filterungen) kann das aber spürbar werden.

useMemo(): einen berechneten Wert merken

import { useMemo } from 'react';

const teuersterWert = useMemo(() => {
  console.log('Teuerste Berechnung läuft...');
  return produkte.reduce((max, p) => (p.price > max ? p.price : max), 0);
}, [produkte]);

useMemo(berechnung, [abhaengigkeiten]) führt berechnung nur dann erneut aus, wenn sich einer der Werte im Abhängigkeits-Array seit dem letzten Rendern geändert hat – ändert sich z. B. nur ein UNABHÄNGIGER State-Wert (wie das Suchfeld, falls es nicht in den Abhängigkeiten steht), wird der zwischengespeicherte ("memoisierte") alte Wert einfach wiederverwendet, ohne die Berechnung erneut auszuführen.

App.jsx erweitern: den teuersten Preis anzeigen

Erweitern Sie src/App.jsx um eine mit useMemo berechnete Statistik:

src/App.jsx
import { useEffect, useMemo, useRef, useState } from 'react';
import ProductCard from './components/ProductCard';

const SAMPLE_PRODUCTS = [
  { sku: 'schuhe-01', name: 'Wanderschuhe', price: 89.99, imageUrl: 'https://picsum.photos/seed/1/300' },
  { sku: 'rucksack-01', name: 'Trekking-Rucksack', price: 59.5, imageUrl: 'https://picsum.photos/seed/2/300' },
  { sku: 'jacke-01', name: 'Regenjacke', price: 74.0, imageUrl: 'https://picsum.photos/seed/3/300' },
];

function App() {
  const [query, setQuery] = useState('');
  const searchInputRef = useRef(null);

  useEffect(() => {
    document.title = `Produktkatalog (${SAMPLE_PRODUCTS.length} Produkte)`;
    searchInputRef.current.focus();
  }, []);

  const gefiltert = SAMPLE_PRODUCTS.filter((produkt) =>
    produkt.name.toLowerCase().includes(query.toLowerCase())
  );

  const teuerstesProdukt = useMemo(() => {
    console.log('Berechne teuerstes Produkt neu...');
    return gefiltert.reduce(
      (max, p) => (p.price > (max?.price ?? 0) ? p : max),
      null
    );
  }, [gefiltert]);

  return (
    <div className="app">
      <h1>Produktkatalog</h1>
      <input
        ref={searchInputRef}
        type="text"
        placeholder="Produkt suchen..."
        value={query}
        onChange={(event) => setQuery(event.target.value)}
      />
      {teuerstesProdukt && (
        <p>Teuerstes Produkt: {teuerstesProdukt.name} ({teuerstesProdukt.price.toFixed(2)} €)</p>
      )}
      <div className="product-grid">
        {gefiltert.map((produkt) => (
          <ProductCard
            key={produkt.sku}
            name={produkt.name}
            price={produkt.price}
            imageUrl={produkt.imageUrl}
            onSelect={() => alert(produkt.name + ' angeklickt')}
          />
        ))}
      </div>
    </div>
  );
}

export default App;

max?.price ?? 0 nutzt "Optional Chaining" (?., gibt undefined statt eines Fehlers zurück, wenn max null ist) und den "Nullish-Coalescing-Operator" (??, liefert den rechten Wert nur bei null/undefined, anders als ||, das auch bei 0 einspringen würde).

useCallback(): eine Funktion merken

useCallback funktioniert genauso wie useMemo, merkt sich aber statt eines Wertes eine FUNKTION selbst – genauer: dieselbe Funktions-REFERENZ über mehrere Render-Durchläufe hinweg, solange sich die Abhängigkeiten nicht ändern.

import { useCallback } from 'react';

const handleProductSelect = useCallback((produkt) => {
  console.log('Ausgewählt:', produkt.name);
}, []); // keine Abhängigkeiten = immer dieselbe Funktionsreferenz

Ohne useCallback erzeugt JEDES Rendern eine BRANDNEUE Funktion – auch wenn ihr Code identisch aussieht, ist es aus JavaScript-Sicht ein neues Objekt im Speicher (fn1 === fn2 wäre false). Das ist meistens egal – wird die Funktion aber an eine mit React.memo optimierte Kind-Komponente übergeben (dazu mehr im Performance-Kapitel des React-für-Profis-Tutorials), verhindert eine "neue" Funktionsreferenz bei jedem Rendern genau die Optimierung, die React.memo eigentlich bringen sollte.

Achtung: Wichtige Faustregel für Einsteiger: Setzen Sie useMemo/useCallback NICHT überall vorsorglich ein. Sie haben selbst einen kleinen Overhead (React muss sich die Abhängigkeiten merken und vergleichen), der bei einfachen Berechnungen/Funktionen mehr kostet, als er einspart. Nutzen Sie sie gezielt: bei WIRKLICH teuren Berechnungen, oder wenn Sie ein konkretes, messbares Performance-Problem haben – nicht "auf Verdacht".