useMemo: What It Is, Caching Computations and React Native

Author: IT Sectr Published: 2026-07-05 Reading time: 10 min

The useMemo hook in React Native memoizes the result of computations between component renders, preventing repeated execution of expensive operations. Unlike useCallback, which memoizes a function, useMemo preserves the returned value and recalculates it only when the specified dependencies change. According to React Docs, 2024, memoization is especially effective for computations with large arrays and complex data transformations. In React Native, every unnecessary re-render creates additional load on the bridge connection between JavaScript and native threads, so proper use of useMemo directly affects the smoothness of animations and interface response speed.

Key Takeaways

  • useMemo — a React hook for memoizing values that caches the result of a function between renders
  • The hook takes two arguments: a compute function and a dependency array
  • The value is recalculated only when at least one dependency changes
  • In React Native, useMemo is critical for optimizing performance of lists and animations
  • Overusing useMemo can worsen performance due to the cost of comparing dependencies

What Is useMemo in React Native

useMemo — is a hook from the standard React library, available in React Native without additional packages. It memoizes the value returned by the passed function and reuses this value on subsequent renders until the dependencies specified in the array change.

The hook's name comes from memoization — an optimization technique where the result of an expensive function is stored in a cache. On subsequent calls with the same arguments, the cached value is returned instead of recomputing.

In the context of React Native, memoization is especially important due to architectural features. Each component re-render sends data through the JavaScript — Native bridge, which takes time. If a component contains expensive computations (filtering a list, sorting, formatting), each re-render will repeat them, blocking the JS thread and causing frame drops.

According to React Native Performance Docs, 2024, the bottleneck is most often not the rendering of native components, but the execution of JavaScript logic between renders. useMemo solves precisely this problem.

How Value Memoization Works

useMemo takes a function and a dependency array, returning a memoized value. React stores the previous value and the dependency array. On each render, React compares the current dependencies with the previous ones using Object.is. If at least one dependency has changed, the function is executed again and the result is stored.

Syntax and Passing Arguments

The useMemo signature is identical on the web and in React Native. The first argument is a parameterless function returning the memoized value. The second is a dependency array, upon whose changes the value will be recalculated.

js
import React, { useMemo } from 'react';

const sortedList = useMemo(() => {
    return items.sort((a, b) => a.name.localeCompare(b.name));
}, [items]);

In this example, sortedList is recalculated only when the reference to the items array changes. If the array content changed but the reference remained the same (mutation), useMemo will not detect the changes — this is an important limitation.

Comparing Dependencies via Object.is

React uses the Object.is algorithm to compare dependencies, which works similarly to strict equality === but handles NaN correctly (+0 and -0 are considered different). This means that for primitive types (strings, numbers, booleans), comparison works by value, while for objects and arrays — by reference.

js
// Object.is({'a': 1}, {'a': 1}) -> false (different refs)
// Object.is(42, 42) -> true (primitive by value)
// Object.is(NaN, NaN) -> true (correct handling of NaN)

Understanding this mechanism is critical: if you pass a new object to dependencies on every render, memoization will be useless because the dependencies will be considered changed each time.

When to Use useMemo

useMemo is justified in three scenarios: expensive computations, passing stable props to child components, and preserving referential identity of objects. In React Native, all three scenarios occur regularly due to the architecture of mobile applications.

Expensive Computations

If a component performs processing of large data arrays (filtering, sorting, grouping) or resource-intensive mathematical operations, useMemo prevents repeating these computations on every re-render. In mobile applications, a typical example is formatting data from an API before displaying it in a list.

Stable Props for Child Components

When a child component is wrapped in React.memo, it only re-renders when its props change. If a prop object is created inside the parent without useMemo, a new reference will be created on every parent render, and the child component will re-render unnecessarily, negating the benefit of React.memo.

Memoization of Style Computations

In React Native, styles often depend on props — for example, element width is calculated based on screen size. useMemo allows computing such dynamic styles only when the input parameters change.

When useMemo Is Useless

useMemo is not a universal optimization tool. In several scenarios, it provides no benefit and can even worsen performance due to the overhead of storing and comparing dependencies. In React Native, where every byte of memory matters, blindly applying useMemo without measuring its effect is an anti-pattern.

The hook brings no benefit in three main cases. First, if the computation is trivial (simple addition, string concatenation), the cost of useMemo exceeds the cost of the computation itself. Second, if dependencies change every render — the function will still execute, and memoization only adds extra work. Third, if the component renders infrequently, the cache storage overhead is not justified.

According to Kent C. Dodds, 2023, before adding useMemo, you should measure the problem using React DevTools Profiler or the built-in Performance Monitor in React Native. If a component re-render takes less than 1 ms, memoization is unnecessary.

  • Trivial computations — addition, concatenation, simple ternary operations
  • Infrequent re-renders — static screens that render once
  • Changing dependencies — if dependencies are new on every render, memoization is useless
  • Primitive values — numbers and strings do not require memoization, they are cheap anyway

useMemo vs useCallback: Comparison

useMemo and useCallback — two memoization hooks from React that are often confused. The difference lies in what they preserve: useMemo returns the result of executing a function (any value), while useCallback returns the function itself. Both take a dependency array, but the syntax differs.

CharacteristicuseMemouseCallback
ReturnsResult of function executionReference to the function
First argumentFunction returning a valueFunction to be memoized
Typical usageCaching computationsStable callbacks for child components
EquivalenceuseMemo(() => fn, deps)useCallback(fn, deps) === useMemo(() => fn, deps)

In practice, useCallback is syntactic sugar over useMemo for cases when you need to memoize a function. In React Native, both hooks are used equally often: useMemo — for data (formatted text, computed styles), useCallback — for event handlers (onPress, onChangeText).

Practical Examples with useMemo

Let’s look at two real-world scenarios for using useMemo in React Native applications. The first is filtering a contact list by search query, the second is computing dynamic styles based on screen size.

Example 1: Search and Filter a List

In this example, useMemo prevents repeated filtering of a large contact list on every render if neither the search query nor the source data has changed.

js
const ContactList = ({ contacts, searchQuery }) => {
    const filteredContacts = useMemo(() => {
        if (!searchQuery.trim()) return contacts;
        const query = searchQuery.toLowerCase();
        return contacts.filter((c) =>
            c.name.toLowerCase().includes(query) ||
            c.phone.includes(query)
        );
    }, [contacts, searchQuery]);

    return (
        <FlatList
            data={filteredContacts}
            renderItem={renderContact}
            keyExtractor={(item) => item.id}
        />
    );
};

Without useMemo, filtering would execute on every render, including those triggered by animations or state changes in other parts of the component. With useMemo, filtering runs only when contacts or searchQuery changes.

Example 2: Computing Dynamic Styles

In React Native, styles often depend on screen dimensions or component props. useMemo allows computing such a style object once and reusing it until the dependencies change.

js
const Card = ({ title, isSelected }) => {
    const cardStyle = useMemo(() => ({
        backgroundColor: isSelected ? '#e3f2fd' : '#ffffff',
        borderWidth: isSelected ? 2 : 1,
        padding: 16,
    }), [isSelected]);

    return (
        <View style={cardStyle}>
            <Text>{title}</Text>
        </View>
    );
};

This approach ensures that the cardStyle object remains stable (same reference) until isSelected changes. If Card is wrapped in React.memo, this pattern prevents unnecessary re-renders of child elements.

Frequently Asked Questions

What does useMemo return?

useMemo returns a memoized value — the result of executing the function passed as the first argument. On subsequent renders, React returns the cached value if the dependencies have not changed.

How is useMemo different from useCallback?

useMemo returns the result of function execution (any value: number, object, JSX), while useCallback returns the function itself. Note that useCallback(fn, deps) is equivalent to useMemo(() => fn, deps).

When is useMemo not needed?

useMemo is useless for trivial computations (addition, concatenation), infrequent re-renders, dependencies that change on every render, and primitive types. Always measure performance before adding useMemo.

Can useMemo worsen performance?

Yes, if used unnecessarily. React stores previous values in memory and compares dependencies on every render. For simple computations, the overhead of these operations exceeds the benefit of memoization.

How to debug useMemo behavior?

Use React DevTools Profiler to measure component render times. In React Native, the Performance Monitor is also available through the developer menu. If a re-render takes less than 1 ms — useMemo is not needed.

Summary

  • useMemo — a React hook for memoizing values, caching the result of a function between renders
  • The hook takes a compute function and a dependency array, recalculating the value only when they change
  • In React Native, useMemo is especially important for optimizing lists, animations, and complex computations
  • Key scenarios: expensive computations, stable props for React.memo, dynamic styles
  • useMemo differs from useCallback: the former returns a value, the latter — a function
  • Overusing useMemo degrades performance due to overhead of storing and comparing dependencies
  • Before adding useMemo, always measure the problem using React DevTools Profiler or Performance Monitor in React Native

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also