Performance — memo, useMemo & useCallback
Making React fast (when you need to)
React is fast by default. But in bigger apps, components can re-render more than necessary, slowing things down. React gives you three tools to avoid wasted work: React.memo, useMemo, and useCallback.
First, an important mindset: do not optimize early. Write clear code first; reach for these only when you actually notice a slowdown.
React.memo — skip re-rendering a component
By default, when a parent re-renders, its children re-render too — even if their props did not change. React.memo tells React: "only re-render this component if its props actually changed."
const ProductCard = React.memo(function ProductCard({ title }) {
return <div>{title}</div>;
});
Now ProductCard re-renders only when title changes — not every time its parent does.
useMemo — remember an expensive calculation
If a component does a heavy calculation on every render, useMemo caches the result and recomputes only when its inputs change:
const sortedList = useMemo(() => {
return hugeList.sort((a, b) => a - b);
}, [hugeList]);
The sort runs only when hugeList changes, not on every unrelated re-render.
useCallback — remember a function
Functions are recreated on every render. If you pass a function as a prop to a memo-ized child, that new function would break the memo. useCallback keeps the same function between renders:
const handleClick = useCallback(() => {
doSomething(id);
}, [id]);
It returns the same function until id changes — so memoized children do not re-render needlessly.
When to use each
- A child re-rendering too often → wrap it in
React.memo. - An expensive calculation repeating →
useMemo. - Passing a function to a memoized child →
useCallback.
React.memoskips re-rendering unchanged components;useMemocaches expensive values;useCallbackcaches functions. Use them only when you measure a real performance problem — not by default.