React Performance Tips: Leveraging useMemo for Smarter Re-renders
If you've been working with React for a while, you've probably heard someone suggest using useMemo
to improve performance. Maybe you've even used it yourself without being entirely sure whether it was necessary.
In this post, we’ll walk through what useMemo
actually does, when it’s useful, and just as importantly—when it’s not.
What Does useMemo Do?
In simple terms, useMemo
is a React hook that helps optimize performance by memoizing the result of a function. That means it remembers the output of a function and only re-computes it when its dependencies change.
Here’s the syntax:
const memoizedValue = useMemo(() => computeSomething(value), [value]);
Every time your component re-renders, the function inside useMemo
will only run again if value
has changed. If it hasn’t, React will return the previously cached result.
This can prevent unnecessary calculations on re-renders and make your app feel faster—especially when working with expensive operations.
When You Don’t Need useMemo
Before jumping into examples, it's important to understand that you should not use useMemo
everywhere.
React is already very fast at re-rendering. If your calculations are quick and the UI is not noticeably slowing down, adding useMemo
adds complexity without much benefit.
Tip: Only use useMemo
when:
You’re seeing performance issues
You're doing expensive calculations
You’re working with large data structures
Practical Examples of useMemo
1. Filtering a Large List
Let’s say you have a long list of items and a search input. Without memoization, the filter function runs every time the component re-renders, even if the input hasn't changed.
const filteredItems = useMemo(() => {
return items.filter(item =>
item.name.toLowerCase().includes(search.toLowerCase()) );
},
[items, search]);
This avoids unnecessary filtering unless items
or search
actually changes.
2. Sorting a Data Table
Sorting a large dataset can be costly. useMemo
helps ensure the sort function only runs when needed.
const sortedData = useMemo(() => {
return [...data].sort((a, b) => {
if (sortBy === 'name')
return a.name.localeCompare(b.name);
if (sortBy === 'date')
return new Date(b.date) - new Date(a.date); return 0; });
},
[data, sortBy]);
Without useMemo
, the data would be re-sorted on every render, even when data
and sortBy
stay the same.
3. Calculating a Total or Derived Value
If you’re working on a shopping cart, for example, and want to display a total price, you can calculate it once using useMemo
.
const totalPrice = useMemo(() => {
return cart.reduce((sum, item) => sum + item.price * item.quantity, 0); }, [cart]);
This is especially helpful if the cart contains many items.
4. Inside Custom Hooks
You can also use useMemo
inside custom hooks to keep logic efficient.
function useVisibleItems(items, filter) {
return useMemo(() => {
return items.filter(item => item.visible && item.type === filter);
},[items, filter]);
}
This keeps your hook performant while keeping the component code clean.
What About useCallback?
It’s common to confuse useMemo
with useCallback
. Here’s a quick distinction:
useMemo
returns a value
useCallback
returns a function
Use useCallback
when you want to prevent a function from being recreated on every render—especially when passing it as a prop to child components.
Key Takeaways
useMemo
helps you avoid recalculating expensive values unnecessarily.
Only use it when the calculation is complex or performance is an issue.
Do not overuse it—adding it everywhere can make your code harder to understand.
Profile your app before optimizing.
React is fast by default, but when you need that extra bit of performance, useMemo
can be a helpful tool—when used in the right situations.