When to Use useMemo vs useRef: A Practical Guide for React Developers

By Saman Batool
June 28, 2025

React’s useMemo and useRef are powerful hooks that solve distinct problems in application performance and state management. Knowing when and why to use them improves your code’s efficiency and readability. Here’s a practical breakdown with examples, including real-world scenarios.

What is useMemo?

useMemo is a React hook that memoizes the result of a function. It returns the cached value unless the specified dependencies change or the function hasn't been evaluated before. This optimizes performance by preventing repeated function calls on each render of a component.

When to Use useMemo

Use useMemo when:

  1. A computationally expensive function is being re-executed unnecessarily.
  2. The return value of a function is used directly in rendering or as a dependency for other hooks.

Example: Avoiding Recomputations

Let’s say you need to calculate the sum of an array before rendering:

``` const numbers = [1, 2, 3, 4, 5]

const sum = useMemo(() => { let total = 0; for (let num of numbers) { total += num; } return total; }, [numbers]);

return The sum is: {sum} ```

Here, useMemo ensures the sum is recalculated only when numbers changes. Without useMemo, the calculation would run on every render.

Real-world Scenario: Calendar Grid Rendering

In a calendar application, calculating and rendering cells for each day can be computationally expensive. Using useMemo helps optimize this process:

const cells = useMemo(() => { return Array.from({length: 7}).map((_, dayIndex) => { const dateNumber = calendarGrid[weekIndex][dayIndex]; const isCurrentDay = viewingCurrentMonthAndYear && dateNumber === currentDate.getDate(); return ( <CalendarCell key={`calendarCell:${weekIndex}:${dayIndex}`} weekIndex={weekIndex} dayIndex={dayIndex} dateNumber={dateNumber} isCurrentDay={isCurrentDay} /> ); }); }, [calendarGrid, weekIndex, currentDate, viewingCurrentMonthAndYear]);

What is useRef?

useRef is a React hook that provides a mutable container. Unlike state, changing a ref does not trigger a component re-render.

When to Use useRef

Use useRef when:

  1. You need to persist a value between renders without causing a re-render.
  2. Accessing DOM elements directly.

Example: Tracking Render Counts

You might want to track how many times a component has rendered:

``` const renderCount = useRef(0);

useEffect(() => { renderCount.current += 1; });

return Render count: {renderCount.current} ```

Here, useRef allows you to persist and update the renderCount without triggering additional renders.

Real-world Scenario: Scrolling in a Chat Application

In a chat interface, you might need to scroll to the latest message whenever new messages arrive. Using useRef ensures this behavior without triggering unnecessary re-renders:

``` const messagesScrollViewRef = useRef(null); useEffect(() => { messagesScrollViewRef.current?.scrollToEnd({animated: true}); }, [messages]);

return ( {messages.map((msg, index) => ( ))} ); ```

Choosing Between useMemo and useRef

Deciding whether to use useMemo or useRef often comes down to the specific needs of your application. Here are some general guidelines to help: * Use useMemo when you need to optimize calculations or prevent redundant computations. This can be especially helpful for computationally expensive operations or to avoid unnecessary renders of dependent child components. * Use useRef when you want to persist mutable data across renders or need direct access to a DOM element. This is ideal for managing scroll positions, focus handling, and tracking non-reactive data (such as a fetched list of items) to avoid unnecessary API requests.

To Consider

While these hooks are powerful, overusing them can complicate your code. Here are some best practices that I’ve learned:

  • Be cautious when using useMemo: While it can be powerful, adding useMemo unnecessarily can add complexity and should only be used when a clear performance issue justifies the optimization. Simpler computations typically don’t benefit much from memoization.

  • Avoid using useRef as a state replacement: useRef does not trigger re-rerenders when its value changes. This makes it unsuitable for managing reactive application state. Use it for non-reactive, persistent values.

Closing Thoughts

Both useMemo and useRef have unique strengths that can lead to a more performant and maintainable codebase. useMemo is great for scenarios where heavy computations or derived values are needed, like optimizing grid rendering in a calendar component. useRef excels in managing mutable references, such as ensuring a chat interface stays scrolled to the latest message or tracking render counts.

By combining these hooks effectively, you can reduce unnecessary renders and manage performance-heavy operations. Whether you’re optimizing a complex application or just starting with React, they are invaluable tools to have in your development toolkit. Happy coding!