Performance optimization in React often brings up two hooks: useMemo
and useCallback
. These can help prevent unnecessary renders, but using them too early or in the wrong places can add needless complexity.
Let’s explore when these hooks actually make a difference—and how to use them effectively.
🚀 What do usememo and usecallback do?
Both hooks help memoize between renders:
useMemo
caches the result of a function.useCallback
caches the function itself.
📦 Usememo: memoizing derived values
Use useMemo
to avoid recalculating expensive values on every render. It only re-computes the value when its dependencies change.
const sortedList = useMemo(() => {
return list.sort((a, b) => a.value - b.value);
}, [list]);
✅ Use it when:
- You're performing heavy calculations (e.g., sorting large datasets).
- The computed value is passed as a prop to a child component that relies on referential equality.
🚫 Avoid it when:
- The computation is cheap.
- The memoized value isn't reused across renders.
🔁 Usecallback: memoizing functions
useCallback
is useful when you want to avoid re-creating a function unless its dependencies change. It helps prevent unnecessary re-renders in child components that rely on function reference.
const handleClick = useCallback(() => {
doSomething();
}, [doSomething]);
✅ Use it when:
- You're passing callback props to memoized child components (e.g.,
React.memo
oruseMemo
). - The function is created inside a component that re-renders frequently.
🚫 Don’t use it just to "optimize"— in many cases, creating the function inline is cheaper and simpler.
🧪 Real example: without usecallback
const Parent = () => {
const [count, setCount] = useState(0);
const handleClick = () => {
console.log('Clicked');
};
return <Child onClick={handleClick} />;
};
In this case, handleClick
is recreated on every render, so if <Child />
is wrapped in React.memo
, it will still re-render.
✅ With usecallback
const handleClick = useCallback(() => {
console.log('Clicked');
}, []);
Now handleClick
is memoized and keeps the same reference unless dependencies change, which can help avoid unnecessary child renders.
🧱 Bonus: react.memo + usecallback
Combine React.memo
and useCallback
for optimal performance in components that rely on reference equality for props.
const Child = React.memo(({ onClick }) => {
return <button onClick={onClick}>Click me</button>;
});
✅ Summary
Hook | Purpose | Use When… |
useMemo | Cache a computed value | Value is expensive or reused |
useCallback | Cache a function definition | Passing callbacks to memoized child |
📌 Conclusion
useMemo
and useCallback
are powerful tools—but they’re not always necessary. Use them to solve specific performance issues, not as a default. Focus first on writing clean, readable code, and then optimize when profiling shows a real need.
Used wisely, these hooks can help your React app run smoother and feel snappier—especially at scale.