Lerne, wann React.memo, useMemo und useCallback deine App wirklich beschleunigen und wann sie sie umsonst verkomplizieren.
Diese Lektion in Kodokon öffnenWenn eine Komponente neu rendert, rendern standardmäßig alle ihre Kinder neu, ob sich ihre Props geändert haben oder nicht. Das ist keine Tragödie: Ein Rendern berührt das DOM nur, wenn sich die Ausgabe ändert. Memoization wird relevant, wenn häufige Renderings auf teure Teilbäume treffen. Drei Werkzeuge, drei Ziele: React.memo überspringt das Rendern einer Komponente, wenn ihre Props flach gleich sind, useMemo speichert einen berechneten Wert zwischen, useCallback speichert eine Funktion zwischen. Alle drei stützen sich auf Referenzgleichheit.
import { memo } from "react";
const Row = memo(function Row({ item, onSelect }) {
return (
<li onClick={() => onSelect(item.id)}>{item.label}</li>
);
});Die Kette ist nur so stark wie ihr schwächstes Glied. Wenn eine einzige Prop bei jedem Rendern eine frische Referenz erhält - eine Inline-Arrow-Funktion, ein Objekt- oder Array-Literal -, schlägt der Vergleich von memo fehl und die Komponente rendert trotzdem neu. useCallback stabilisiert die Referenz der Funktion, sodass der Vergleich gelingt.
import { useCallback } from "react";
function List({ items }) {
const handleSelect = useCallback((id) => {
console.log("selected:", id);
}, []);
return (
<ul>
{items.map((item) => (
<Row
key={item.id}
item={item}
onSelect={handleSelect}
/>
))}
</ul>
);
}useMemo hat zwei legitime Verwendungen: eine wirklich teure Berechnung zu vermeiden (Tausende Elemente sortieren oder aggregieren) und eine Referenz zu stabilisieren, die von einem memoisierten Kind konsumiert oder in den Abhängigkeiten eines Effekts aufgeführt wird. Bei einer trivialen Berechnung kostet der Cache mehr, als er spart: Abhängigkeitsvergleich, gebundener Speicher, schwerere Lesbarkeit.
import { useMemo } from "react";
function Stats({ orders }) {
const total = useMemo(() => {
return orders.reduce(
(sum, order) => sum + order.amount,
0
);
}, [orders]);
return <p>Total: {total} €</p>;
}