Join the discussion
Comments
Loading comments...
Cookie preferences
We use essential cookies for sign-in and preferences. With your permission, we also use basic analytics to improve lessons.
Join the discussion
Loading comments...
We use essential cookies for sign-in and preferences. With your permission, we also use basic analytics to improve lessons.
Wie React berechnete Werte und Funktionsreferenzen zwischenspeichert, um teure Neuberechnungen zu überspringen.
Memoisierung ist eine Caching-Technik, bei der React das Ergebnis einer teuren Berechnung speichert und bei nachfolgenden Renderings das gecachte Ergebnis zurückgibt — die Berechnung wird vollständig übersprungen, wenn sich die Eingaben nicht geändert haben. useMemo cached berechnete Werte. useCallback cached Funktionsreferenzen. Beide verwenden ein Dependency-Array, um zu entscheiden, wann neu berechnet werden soll.
useMemo(() => teureBerechnung(a, b), [a, b]) ruft die Funktion beim ersten Rendering auf und speichert das Ergebnis. Bei Re-Renderings prüft React, ob sich a oder b geändert hat. Falls nicht, gibt es das gecachte Ergebnis zurück, ohne die Funktion erneut aufzurufen.
useCallback(fn, [deps]) ist äquivalent zu useMemo(() => fn, [deps]). Anstatt den Rückgabewert zu cachen, cached es das Funktionsobjekt selbst. Dies ist wichtig, weil JavaScript bei jedem Rendering ein neues Funktionsobjekt erstellt — was die referenzielle Gleichheit für Kind-Komponenten-Props bricht.
React vergleicht jeden Dep-Wert mit Object.is() (strenge Gleichheit). Primitive Werte (Zahlen, Strings, Booleans) werden nach Wert verglichen. Objekte und Arrays werden nach Referenz verglichen — daher löst ein neues Objektliteral '{''}' in Deps immer eine Neuberechnung aus.
Wenn alle Deps gleich den Deps des vorherigen Renderings sind, gibt React sofort den memoiserten Wert zurück, ohne die Factory-Funktion aufzurufen. Die Komponente rendert dennoch — aber die teure Berechnung wird übersprungen.
Wenn sich ein Dep geändert hat, ruft React die Factory-Funktion erneut auf, speichert das neue Ergebnis und gibt es zurück. Der alte gecachte Wert wird verworfen.
Cached den Rückgabewert einer Berechnung. Berechnet nur neu, wenn sich Deps ändern. Nützlich für teure Berechnungen, die von Props/Zustand abgeleitet werden.
Cached eine Funktionsreferenz. Äquivalent zu useMemo(() => fn, deps). Entscheidend beim Übergeben von Callbacks an memoisierte Kind-Komponenten.
Zwei Objekte/Arrays sind nur gleich, wenn sie auf dieselbe Speicheradresse zeigen. '{''}' === '{''}' ist false. useMemo/useCallback erhalten die Identität über Renderings hinweg.
Das zweite Argument für useMemo/useCallback. React vergleicht diese Werte zwischen Renderings, um zu entscheiden, ob neu berechnet werden soll.
Higher-Order-Komponente, die die Render-Ausgabe einer Komponente memoisiert. Funktioniert am besten in Kombination mit useCallback zur Stabilisierung von Callback-Props.
1function ParentComponent({ items }) {2 const [filter, setFilter] = useState('');3 const [count, setCount] = useState(0);45 // useMemo: expensive filter only recomputes when items/filter change6 const filteredItems = useMemo(7 () => items.filter(item => item.name.includes(filter)),8 [items, filter]9 );1011 // useCallback: stable reference, doesn't cause Child re-render12 // when only 'count' changes13 const handleSelect = useCallback((id) => {14 console.log('Selected:', id);15 }, []); // no deps — function never needs to change1617 return (18 <>19 <button onClick={() => setCount(c => c + 1)}>Count: {count}</button>20 <MemoizedChild items={filteredItems} onSelect={handleSelect} />21 </>22 );23}2425const MemoizedChild = React.memo(({ items, onSelect }) => {26 // Only re-renders when items or onSelect reference changes27 return items.map(i => <Item key={i.id} item={i} onSelect={onSelect} />);28});
Ohne Memoisierung erstellt jedes erneute Rendern der Elternkomponente neue Objekt-/Funktionsreferenzen, was dazu führt, dass mit React.memo umhüllte Kinder unnötigerweise neu gerendert werden. useMemo und useCallback erhalten die referenzielle Stabilität, machen React.memo effektiv und verhindern kaskadierende Re-Renderings in großen Komponentenbäumen.
Your analytics dashboard processes 10,000 rows of sales data to calculate aggregates (sum, average, percentiles) and format display values. A clock that updates every second causes the entire dashboard to re-render — and the 50ms data processing runs every second.
The data transformation runs inside the render function without memoization. Every re-render (even from the clock ticker) recomputes all 10,000 rows. The dashboard becomes sluggish because 50ms of computation blocks the main thread on every tick.
Wrap the data transformation in `useMemo(() => processData(salesData), [salesData])`. Now the heavy computation only re-runs when `salesData` actually changes. Clock ticks cause re-renders but skip the 50ms computation entirely — React reuses the cached result.
Takeaway: useMemo is designed for expensive computations, not every value. The general guideline: if a computation takes more than 1ms or processes more than 100 items, it's a candidate for useMemo. Profile before optimizing — don't guess.
You wrap a heavy `DataTable` component in React.memo, but React DevTools still shows it re-renders every time the parent's unrelated state changes. Memo appears to 'not work.'
The parent passes `onRowClick={(id) => handleClick(id)}` — an inline arrow function. Every parent render creates a NEW function reference. React.memo compares props by reference: `oldFn !== newFn`, so it always re-renders. Memo is working correctly — the props ARE different every time.
Wrap the handler in `useCallback`: `const onRowClick = useCallback((id) => handleClick(id), [handleClick])`. Now the function reference is stable across renders. React.memo's shallow comparison sees identical props and correctly skips re-rendering the DataTable.
Takeaway: React.memo and useCallback/useMemo are a PAIR — they must be used together. React.memo is useless if any prop is an unstable reference (inline function, inline object, inline array). Always stabilize props with useCallback/useMemo before wrapping a child in React.memo.