Wann und wie man useMemo in React verwendet

Wann und wie man useMemo in React verwendet

Wenn Sie eine React-App gebaut haben, die langsamer läuft als erwartet, haben Sie sich vielleicht schon gefragt: Was wird bei jedem Rendern neu berechnet und wie verhindere ich das? Genau hier zeigt sich, wie hilfreich useMemo sein kann. Richtig eingesetzt, verhindert er aufwendige Neuberechnungen und sorgt dafür, dass Werte für Kindkomponenten stabil bleiben. Falsch verwendet, entsteht unnötiger Aufwand und Verwirrung.

Dieses useMemo-Leitfaden von unserer Frontend Entwicklung Agentur erklärt, wann und wie man useMemo nutzt, was der Hook tatsächlich macht, wo er hilfreich ist, wo nicht und wie er mit React.memo bzw. useCallback zusammenspielt. Wir gehen reale Beispiele durch, die typische Einsatzszenarien aus dem Entwickleralltag abdecken. Später finden Sie Hinweise zu useMemo in React 19 sowie eine kleine Checkliste, die bei der Einstellung eines Software-Entwickler wichtig sind und die Sie im Editor griffbereit haben können.

useMemo in React – einfach erklärt

useMemo ist ein Hook, dessen Hauptaufgabe es ist, einen zwischengespeicherten Wert zurückzugeben. Er hat zwei Argumente: eine Callback-Funktion und ein Abhängigkeitsarray. Beim ersten Rendern führt React den Callback aus und speichert das Ergebnis. Bei jedem weiteren Rendern gibt React diesen gespeicherten Wert zurück, solange sich die Abhängigkeiten nicht geändert haben. Sobald sich eine Abhängigkeit ändert, berechnet React den Wert neu und speichert das aktualisierte Ergebnis. Dieser Ablauf wiederholt sich, bis die Komponente aus dem DOM entfernt wird.

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

Quick Mental model: treat useMemo like a tiny local cache keyed by your dependencies.

Beim Einsatz von useMemo gibt es ein paar Punkte zu beachten. Erstens speichert es die Werte, nicht Funktionen. Wie oben erläutert, führt React den übergebenen Callback mindestens einmal aus, um den zurückgegebenen Wert zu speichern. Wenn Sie tatsächlich eine Funktionsimplementierung festhalten möchten, ist useCallback vermutlich die bessere Wahl. Auf dieses Thema kommen wir später zurück.

Zweitens „friert“ useMemo keine Variablen ein. Die angegebenen Abhängigkeiten haben ihren Zweck: Ändert sich eine davon, wird der Wert neu berechnet. Sie können useMemo zwar mit einem leeren Abhängigkeitsarray verwenden (dann wird der Wert nur einmal berechnet). Diese Variante sollte jedoch auf einen klar erkennbaren Performance-Engpass oder den Bedarf stabiler Referenzen zurückgehen und nicht als Standardlösung dienen.

Abschließend sollten Sie useMemo nicht einsetzen, um Logikprobleme zu beheben oder Nebenwirkungen zu kontrollieren. Der Callback muss eine reine Funktion sein; andernfalls können Fehler in der Weblösung entstehen, die sich kaum debuggen lassen. Falls Nebenwirkungen behandelt werden sollen, ist der useEffect-Hook die richtige Stelle dafür.

Schnelles mentales Modell: Verwenden Sie useMemo wie einen kleinen lokalen Zwischenspeicher, der über Ihre Abhängigkeiten gesteuert wird.

Wann Sie useMemo anwenden sollten (Faustregel)

Eine praktische Orientierungshilfe für Ihre Entscheidung:

  • Ist die Berechnung tatsächlich kompliziert?
  • Läuft sie häufig (bei Re-Renders)?
  • Würde das Caching viel Arbeit vermeiden oder Re-Renders im weiteren Verlauf reduzieren (indem Referenzen stabilisiert werden)?

Wenn Sie mindestens eine dieser Fragen mit “Nein” beantworten können, brauchen Sie useMemo möglicherweise nicht.

Zuerst messen
Bevor Sie Optimierungen vornehmen, ist es immer wichtig zu verstehen, wo in Ihrer App Probleme auftreten. Dafür können Sie Tools wie den React Profiler oder das Performance-Panel Ihres Browsers verwenden. Sobald Sie ein umfassendes Bild davon haben, welche Teile Ihrer Anwendung langsam laufen, können Sie gezielt mit der Optimierung beginnen. So vermeiden Sie Überengineering in Bereichen Ihrer App, die bereits effizient funktionieren.

Nun wollen wir uns einige typische Szenarien ansehen, in denen useMemo praktisch ist.

Szenario 1: Aufwendige Berechnung, die Sie nicht wiederholen möchten

Datenmanipulation ist eine häufig genutzte Technik in React-Anwendungen. Dazu gehören Aufgaben wie Sortieren, Filtern oder Aggregieren, um Ihre Daten gemäß den Design- und UX-Vorgaben vorzubereiten. Eine solche Aufgabe in Ihrer Komponente bedeutet, dass bei jedem Rendern eine aufwendige Transformation erneut berechnet werden könnte, was in manchen Fällen die Gesamtleistung Ihrer App beeinträchtigen kann.

Wenn eine solche Situation jemals auftritt, können Sie useMemo zur Verbesserung einsetzen. Es speichert das berechnete Ergebnis und verwendet es bei jedem nachfolgenden Render, solange die Eingaben unverändert bleiben.

Schauen wir uns folgendes React useMemo-Beispiel an:

import { useMemo, useState } from "react";
​
function Products({ items }) {
const [query, setQuery] = useState("");
const [sortBy, setSortBy] = useState("price"); // "price" | "rating"
​
const filteredAndSorted = useMemo(() => {
const q = query.toLowerCase().trim();
​
// expensive: filter + sort on a big list
const filtered = items.filter((p) =>
  p.name.toLowerCase().includes(q) ||      p.category.toLowerCase().includes(q)
);
​
const sorted = [...filtered].sort((a, b) =>
  sortBy === "price" ? a.price - b.price : b.rating - a.rating
);
​
return sorted;
}, [items, query, sortBy]);
​
return (
<>
  <Controls query={query} onQueryChange={setQuery} sortBy={sortBy} onSortChange={setSortBy} />
  <List data={filteredAndSorted} />
</>
);
}

Wenn die Sortierfunktion ohne useMemo implementiert wird, bedeutet das, dass bei jedem Re-Render des übergeordneten Elements eine neue Filter- und Sortieroperation für eine möglicherweise große Liste ausgeführt wird. Die Leistungsoptimierung mit useMemo verhindert die erneute Berechnung, solange items, query und sortBy unverändert bleiben.

Das Identifizieren von Codebereichen mit aufwendigen Berechnungen und deren Einbettung in useMemo kann dazu beitragen, die Performance Ihrer App zu verbessern.

Szenario 2: Stabilisierung von Objekt-/Array-Props, um Re-Renders von Kindkomponenten zu vermeiden

Manchmal haben Sie eine aufwendige Komponente, die Sie speichern möchten, um unnötige Re-Renders zu vermeiden. Dies erreichen Sie mit React.memo, das eine zwischengespeicherte Version der Komponente beibehält und keine erneuten Re-Renders auslöst, solange sich die Props der Komponente nicht ändern.

Angenommen, Sie müssen eine Liste oder ein Objekt als Prop  dieser Komponente übergeben. In diesem Fall geben Sie bei jedem Rendern ein neues Objekt- oder Array-Literal weiter. Referenziell ist es neu, sodass React.memo eine Prop-Änderung erkennt und die Kindkomponente trotzdem erneut rendert.

Um dieses Problem zu verhindern, können Sie das Objekt oder Array mit useMemo speichern, sodass die Referenz stabil bleibt, solange sich der Inhalt nicht geändert hat.

import { useMemo } from "react";
import { memo } from "react";
​
const Chart = memo(function Chart({ options }) {
// ... renders only if options reference changes
return <div>{/* chart */}</div>;
});
​
function Dashboard({ theme, currency }) {
const chartOptions = useMemo(() => ({
theme,
axis: { showGrid: true },
currency,
}), [theme, currency]);
​
return <Chart options={chartOptions} />;
}

Im obigen Beispiel behält chartOptions dieselbe Referenz bei, bis sich theme oder currency ändern. Dadurch wird die Chart-Komponente nicht unnötig neu gerendert. Dies ist eine klassische React-Memoization-Technik, um überflüssige Re-Renders in React zu vermeiden.

Szenario 3: Abgeleiteter State statt zusätzlichem useState

Ein häufiger Fehler besteht darin, useState übermäßig zu verwenden, um Daten zu speichern, die von einer Berechnung aus dem Wert eines anderen States abhängen. Zum Beispiel:

function Cart({ items }) {
const [subtotal, setSubtotal] = useState(0);
​
useEffect(()=> {
const result = items.reduce((sum, it) => sum + it.price * it.qty, 0)
​
setSubtotal(result)
}, [items])
​
const tax = subtotal * 0.21;
const total = subtotal + tax;
​
return <Summary subtotal={subtotal} tax={tax} total={total} />;
}

Im vorherigen Beispiel wird der Subtotal jedes Mal berechnet, wenn sich die items ändern, und das Ergebnis anschließend in einem neuen State gespeichert. Tatsächlich brauchen Sie in diesem Fall jedoch gar kein weiteres useState, Sie brauchen einen Wert, der aus bestehendem State oder Props abgeleitet wird.

Statt der vorherigen Implementierung können Sie die Quelle der Wahrheit eindeutig belassen und den abgeleiteten Wert mit useMemo berechnen.

function Cart({ items }) {
const subtotal = useMemo(
() => items.reduce((sum, it) => sum + it.price * it.qty, 0),
[items]
);
const tax = subtotal * 0.21;
const total = subtotal + tax;
​
return <Summary subtotal={subtotal} tax={tax} total={total} />;
}

Auf diese Art und Weise vermeiden Sie einen doppelten Zustand und müssen nicht mehr raten, welcher Wert tatsächlich korrekt ist. Lassen Sie einfach useMemo die Zwischensumme neu berechnen, sobald sich die Items ändern.

Szenario 4: Aufwendige Formatierung (i18n, Zahlen-/Datumsformatierung)

Wir haben bereits erwähnt, dass das Formatieren großer Listen überraschend teuer sein kann. Eine weitere gängige Technik besteht darin, die Formatierer zwischenzuspeichern und sie anschließend in Ihrer Komponente zu verwenden. Zum Beispiel:

function PriceCell({ value, locale, currency }) {
const formatter = useMemo(() => new Intl.NumberFormat(locale, {
style: "currency",
currency
}), [locale, currency]);
​
return <span>{formatter.format(value)}</span>;
}

Auf diese Weise erstellen Sie den Formatierer nur einmal und wenden ihn dann auf alle Elemente an, die formatiert werden sollen.

useMemo vs useCallback (und wie React.memo hineinpasst)

useMemo, useCallback und React.memo sind drei Möglichkeiten, Memoisierung zu nutzen, um die Leistung Ihrer Anwendung zu verbessern. Sie funktionieren jedoch auf unterschiedliche Art und Weise. useMemo wird verwendet, um einen Wert zu memoisieren (einschließlich Arrays, Objekten, Zahlen, Strings und/oder JSX-Bäumen). useCallback hingegen memoisert eine Funktionsreferenz, die später im Code aufgerufen werden kann. React.memo dient dazu, eine Komponente zu memoisieren, damit spätere Re-Renders übersprungen werden, sofern sich die Props nur oberflächlich geändert haben.

Da diese drei Tools zu unterschiedlichen Zwecken dienen, kombiniert man sie häufig, wie im folgenden Beispiel: 

import { useMemo, useCallback, useState, memo } from "react";
​
const Row = memo(function Row({ item, onSelect, style }) {
// rerenders only if item/onSelect/style identity changes
return <div style={style} onClick={() => onSelect(item.id)}>{item.name}</div>;
});
​
function Table({ items }) {
const [selected, setSelected] = useState(null);
​
const style = useMemo(() => ({ padding: 8, cursor: "pointer" }), []);
const handleSelect = useCallback((id) => setSelected(id), []);
​
return items.map((it) => (
<Row key={it.id} item={it} onSelect={handleSelect} style={style} />
));
}

Zusammengefasst: useMemo stabilisiert Werte, useCallback stabilisiert Funktionen, und React.memo verhindert überflüssige Renderings aufgrund dieser Stabilität. Dieses Trio bildet die Grundlage für die Optimierung funktionaler React-Komponenten.

Häufige Fehler (und wie Sie sie vermeiden)

Auch wenn useMemo ein leistungsfähiges Werkzeug ist, sollte es mit Bedacht eingesetzt werden. Hier stellen wir einige typische Fehler vor:

1) Günstige Operationen memoisieren
Jedes useMemo hat einen kleinen Overhead. Verpacken Sie keine trivialen Berechnungen darin.

2) Falsche Abhängigkeiten
Wenn Sie eine Abhängigkeit vergessen, erhalten Sie veraltete Werte. Wenn Sie zu viele angeben, wird häufiger neu berechnet als nötig. Folgen Sie der ESLint-Regel react-hooks/exhaustive-deps und strukturieren Sie den Code so um, dass die Abhängigkeitsliste korrekt und minimal ist.

3) Versteckte Mutationen
Das Ergebnis von useMemo sollte unveränderlich sein. Wenn irgendwo im Code ein Wert des Stores mutiert wird, kann dies die ursprünglichen Annahmen durchbrechen. Falls der Wert später verändert werden muss, sollten Sie einen anderen Ansatz wählen statt useMemo.

4) Nebenwirkungen von useMemo.
Wie oben erwähnt, sollte die Callback-Funktion, die Sie an useMemo übergeben, eine reine Funktion sein (d. h. sie sollte bei gleichen Eingaben immer dasselbe Ergebnis liefern). Wenn Sie Subscriptions, Logging oder DOM-Änderungen durchführen müssen, verwenden Sie dafür die entsprechenden React Hooks (meistens useEffect, in speziellen Fällen useLayoutEffect).

5) Von useMemo erwarten, dass es „langsame“ Rendering-Bäume löst.
Wenn das Rendern des untergeordneten Baums bereits langsam ist, sollten Sie eher andere Ansätze verwenden, statt ihn einfach in ein useMemo zu packen. Auch wenn das eine kleine Verbesserung bringen kann, ist das nicht der eigentliche Zweck von useMemo. In solchen Fällen sollten Sie Komponenten aufteilen, große Listen virtualisieren oder Teilbäume bzw. Komponenten mit React.memo memoisieren. useMemo sollte diese Strategien ergänzen, nicht ersetzen.

Wann useMemo sinnvoll ist

Unten finden Sie zwei praktische Entscheidungsbäume, die Ihnen bei der Entscheidung helfen, ob useMemo in Ihrer Komponente sinnvoll ist.

Entscheidungsbaum 1 für den Einsatz von React useMemo Entscheidungsbaum 2 für den Einsatz von React useMemo

Den Effekt messen

Angenommen, Sie haben ein Leistungsproblem in Ihrer App entdeckt. Sie planen useMemo zu verwenden, um bestimmte Berechnungen zu vermeiden und Ressourcen zu sparen. Doch nachdem Sie es implementiert haben, sehen Sie keine Verbesserung. Im schlimmsten Fall wirkt der erste Render sogar langsamer.

Wie Sie sich denken können, ist Memoisierung nicht kostenlos. Sie erfordert zumindest eine erste Berechnung, um den Callback auszuführen und den Startwert zu speichern. Und selbst wenn spätere Re-Renders der Komponente schneller werden könnten, ist das womöglich gar nicht der eigentliche Grund für Ihr Performance-Problem. Daher sollten Sie immer vor und nach der Einführung von useMemo messen, ob sich der Einsatz wirklich lohnt. Für die Messung eignen sich unter anderem:

  • React Profiler: Interaktionen aufzeichnen und die Commit-Zeiten von Komponenten mit komplexen Berechnungen prüfen
  • Console Timings: Die schwere Berechnung kurzzeitig mit console.time / console.timeEnd umschließen.
  • Flamegraphs in der Performance-Karte: Wiederkehrende „Hot Functions“ nach Leerlaufphasen identifizieren.

Wenn Sie keine Verbesserung sehen, entfernen Sie das Memo wieder. Vereinfachen Sie den Code. Echte Verbesserungen erkennt man an messbaren Daten, nicht am Gefühl.

Hinweise zu useMemo in React 19

React 19 hat einige Funktionen eingeführt, die auf bessere Performance abzielen. Schauen wir kurz darauf, wie sie mit useMemo zusammenspielen.

Grundsätzlich hat sich an der Nutzung von useMemo im Vergleich zu früheren Versionen grundsätzlich nichts geändert: Es liefert weiterhin einen memoiserten Wert, der an Abhängigkeiten gekoppelt ist. Erwähnenswert ist jedoch, dass Concurrent Rendering besser mit Memoisierung harmoniert. Memoisierte Werte bleiben über Transitionen hinweg stabil, und React kann UI im Hintergrund vorbereiten, während es für die aktuelle Ansicht den zwischengespeicherten Wert nutzt.

Gleichzeitig reduzieren neue Muster für das Laden von Ressourcen, zum Beispiel Suspense und Concurrent Data Fetching, die Notwendigkeit, ‚alles‘ im Render-Schritt vorab zu berechnen. Damit wird deutlich, dass useMemo auf reine, synchrone Berechnungen und stabile Referenzen für Props fokussiert bleiben sollte.

Anti-Patterns, die Sie vermeiden sollten

Bei der Verwendung von useMemo in React Software Lösungen sollten Sie einige typische Fehlmuster vermeiden. Viele davon wurden zuvor schon erwähnt, daher hier eine kurze Zusammenfassung:

  • Alles in useMemo packen. Das erzeugt unnötigen Lärm und Overhead. Es bringt kaum Vorteile und verlangsamt die Performance.
  • Instabile Abhängigkeiten memoisieren. Wenn Abhängigkeiten bei jedem Render neu entstehen (z. B. eine neue Funktion ohne useCallback), wird die Berechnung trotzdem jedes Mal ausgeführt.
  • useMemo als Ersatz für sauberen Code nutzen. Wenn eine Berechnung langsam ist, weil sie zu komplex ist, sollte man eher refaktorieren oder Vorberechnungen auf den Server verlagern, statt blind zu memoisieren.

Tests und Typen

 Zwei wichtige Erkenntnisse für Tests und Typen:

  • In Unit-Tests sollten Sie nicht useMemo selbst testen, sondern die zugrunde liegende Berechnungsfunktion.
  • Typisieren Sie den Rückgabewert, nicht den Hook. Lassen Sie die Type-Inferenz laufen.
const total: number = useMemo(() => calcTotal(items), [items]);

Schnellübersicht: useMemo React-Checkliste

Diese Checkliste hilft Ihnen dabei, useMemo korrekt zu verwenden:

UseMemo React Checkliste

FAQ

Ist die Zwischenspeicherung durch useMemo garantiert?

React kann zwischengespeicherte Werte bei Speicherdruck verwerfen. Tatsächlich verhält es sich jedoch wie ein stabiler Cache, der an die Abhängigkeiten gebunden ist. Man sollte sich aber nicht über mehrere Mounts hinweg darauf verlassen.

Kann useMemo useState ersetzen?

Nein. Es dient für abgeleitete Werte, nicht als Speicher.

Hilft useMemo bei asynchronen Vorgängen?

Nein. Es ist für synchrone Berechnungen während des Renderns gedacht. Für asynchrone Abläufe nutzt man useEffect oder Suspense.

Fazit (und wie es weitergeht)

useMemo ist kein Allheilmittel, aber ein verlässliches Werkzeug bei teuren Berechnungen oder Referenzproblemen, die unnötige Re-Renders auslösen. Erst messen, dann gezielt einsetzen. In Kombination mit React.memo und useCallback ergibt sich eine solide Performance-Strategie. Sie ist praktisch vor allem bei großen Listen, abgeleiteten Daten und Konfigurationsobjekten, die an memoisierte Kindkomponenten weitergegeben werden.

Wenn Ihr Team eine große Performance-Optimierung plant, lohnt es sich, Renderpfade zu prüfen, Komponenten klar zu trennen und lange Listen zu virtualisieren, bevor man jede Kleinigkeit mikrooptimiert. Memoisierung funktioniert am besten als Teil eines größeren Optimierungsansatzes.

Wer einen Verbesserungsfahrplan erstellt oder eine ältere UI auf eine moderne, memo-freundliche Architektur umstellt, kann professionelle React Entwicklung in Betracht ziehen — von Profiling und Performance-Tuning über den Aufbau einer Komponentenbibliothek bis hin zu Schulungen für einen reibungslosen und geradlinigen Übergang.