React Performance Tips: Leveraging useMemo for Smarter Re-renders

React Performance Tips: Leveraging useMemo for Smarter Re-renders

Rito Nguyen

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.