useMemo Hook in React JS
The useMemo Hook is a built-in React Hook that helps improve performance by caching the result of a calculation between component re-renders. React can reuse the previously calculated value when its dependencies have not changed, instead of performing the calculation again. It is particularly useful when working with expensive calculations, large lists, filtering, sorting, and optimized child components.
Course: JustAcademy React JS Training Course
Course Demo: Register for React JS Course Demo
1. What Is the useMemo Hook?
useMemo is used to cache the result of a calculation so React can reuse it during later renders when the dependencies remain unchanged. This technique is called memoization.
By default, React executes the component function again when the component re-renders. Calculations inside the component body are normally performed again. If a calculation is expensive, useMemo can help avoid unnecessary recalculations.
Syntax
const cachedValue = useMemo(() => {
return calculateValue();
}, [dependency1, dependency2]);
Explanation:
useMemo is the React Hook used for memoization.
() => calculateValue() is the calculation function.
[dependency1, dependency2] is the dependency array.
cachedValue stores the calculated result returned by the Hook.
2. Why Do We Use useMemo?
- Improve performance: Avoid repeating expensive calculations when the relevant inputs have not changed.
- Optimize list operations: Cache the results of filtering, sorting, or transforming large arrays.
- Preserve value references: Reuse the same object or array reference while dependencies remain unchanged.
- Support memoized child components: Help prevent unnecessary child re-renders when the child uses
memo and its props remain unchanged.
- Stabilize dependencies: Sometimes prevent an object dependency from changing on every render.
Important: useMemo is a performance optimization, not a requirement for every calculation. Most simple calculations do not need it.
3. How Does useMemo Work?
- React renders the component for the first time.
- The calculation function passed to
useMemo runs.
- React returns the calculated value and caches it.
- When the component renders again, React compares the current dependencies with the previous ones.
- If the dependencies have not changed, React can reuse the cached value.
- If one or more dependencies have changed, React recalculates the value.
Flow Diagram
Component Renders
|
v
useMemo Checks Dependencies
|
v
Have Dependencies Changed?
|
+---+---+
| |
No Yes
| |
v v
Reuse Recalculate
Cached the Value
Value |
| |
+---+---+
|
v
Return the Value
React compares dependency values using Object.is. The dependency array must contain the reactive values used by the calculation.
4. First Example: useMemo with a Simple Calculation
This example calculates the square of a number using useMemo.
import { useMemo, useState } from "react";
function SquareCalculator() {
const [number, setNumber] = useState(2);
const [theme, setTheme] = useState(false);
const square = useMemo(() => {
console.log("Calculating square...");
return number * number;
}, [number]);
return (
<div style={{
background: theme ? "#222" : "#fff",
color: theme ? "#fff" : "#222",
padding: "20px"
}}>
<h2>Square: {square}</h2>
<button onClick={() => setNumber(number + 1)}>
Increase Number
</button>
<button onClick={() => setTheme(!theme)}>
Toggle Theme
</button>
</div>
);
}
export default SquareCalculator;
Explanation:
number stores the number entered into the calculation.
square stores the result of number * number.
- The dependency array contains
[number].
- When the number changes, React recalculates the square.
- When only the theme changes, React can reuse the cached square.
This calculation is simple, so memoization is not necessary in a real application. It is used here to demonstrate how the Hook works.
5. useMemo with Expensive Calculations
An expensive calculation takes a noticeable amount of time or processing power. Examples include processing large datasets, filtering thousands of records, or performing complex mathematical operations.
Example
import { useMemo, useState } from "react";
function ExpensiveCalculation() {
const [number, setNumber] = useState(100);
const [theme, setTheme] = useState(false);
const result = useMemo(() => {
let total = 0;
for (let i = 0; i < number * 1000; i++) {
total += i;
}
return total;
}, [number]);
return (
<div style={{ color: theme ? "blue" : "black" }}>
<h2>Result: {result}</h2>
<button onClick={() => setNumber(number + 10)}>
Change Number
</button>
<button onClick={() => setTheme(!theme)}>
Change Theme
</button>
</div>
);
}
export default ExpensiveCalculation;
Explanation: The calculation runs when the component initially renders and when number changes. If only theme changes, React can reuse the cached result.
Note: This is a demonstration, not a benchmark. Use profiling to determine whether a calculation is expensive enough to benefit from memoization.
6. Understanding the Dependency Array
The dependency array tells React which reactive values affect the calculation. When any dependency changes, React recalculates the value.
Example with One Dependency
const doubled = useMemo(() => {
return count * 2;
}, [count]);
The calculation is repeated when count changes.
Example with Multiple Dependencies
const total = useMemo(() => {
return price * quantity;
}, [price, quantity]);
The calculation is repeated when either price or quantity changes.
Example with an Empty Dependency Array
const initialMessage = useMemo(() => {
return "Welcome to React";
}, []);
The calculation normally runs during the initial render and its result is reused on subsequent renders. React may discard the cached value for specific reasons, so useMemo should not be used as a guarantee that a value will exist permanently.
Important Dependency Rules
- Include all reactive values used inside the calculation.
- Do not leave out dependencies simply to prevent recalculation.
- Keep the dependency array inline and maintain a constant number of dependencies.
- React compares dependency values using
Object.is.
7. useMemo with Arrays and Filtering
useMemo is often useful when filtering or transforming large arrays. It can reuse the filtered result when the source array and filter value remain unchanged.
Example: Product Search
import { useMemo, useState } from "react";
const products = [
{ id: 1, name: "Laptop", price: 50000 },
{ id: 2, name: "Mobile", price: 20000 },
{ id: 3, name: "Headphones", price: 2000 },
{ id: 4, name: "Keyboard", price: 1500 }
];
function ProductSearch() {
const [search, setSearch] = useState("");
const [showAffordable, setShowAffordable] = useState(false);
const filteredProducts = useMemo(() => {
return products.filter(product => {
const matchesSearch = product.name
.toLowerCase()
.includes(search.toLowerCase());
const matchesPrice = !showAffordable || product.price <= 20000;
return matchesSearch && matchesPrice;
});
}, [search, showAffordable]);
return (
<div>
<h2>Product Search</h2>
<input
type="text"
value={search}
onChange={event => setSearch(event.target.value)}
placeholder="Search products"
/>
<label>
<input
type="checkbox"
checked={showAffordable}
onChange={event => setShowAffordable(event.target.checked)}
/>
Show products up to ₹20,000
</label>
<ul>
{filteredProducts.map(product => (
<li key={product.id}>
{product.name} - ₹{product.price}
</li>
))}
</ul>
</div>
);
}
export default ProductSearch;
Explanation:
products contains the product data.
search stores the search text.
showAffordable controls the price filter.
filteredProducts stores the memoized filtered array.
- The filtering calculation runs again when either dependency changes.
For a small array, filtering directly may be perfectly adequate. Memoization is most useful when the calculation is costly or when preserving the array reference helps an optimized child component.
8. useMemo with Object Values
JavaScript creates a new object when an object literal is evaluated. Even if two objects contain identical properties, they are different references.
Example
const user = useMemo(() => {
return {
name: "Amit",
role: "Developer"
};
}, []);
React can reuse this object reference between renders while the cached value is retained.
When Is This Useful?
- When an object is passed as a prop to a child wrapped with
memo.
- When a memoized object is used as a dependency of another Hook.
- When creating the object is part of an expensive calculation.
Do not use useMemo for every object. Often, restructuring the code is simpler and more reliable than memoizing an object solely to preserve its reference.
9. useMemo with Child Components and memo
The memo function can help a child component skip re-rendering when its props remain unchanged. However, if the parent creates a new array or object on every render, the child may receive a different prop reference each time.
Example
import { memo, useMemo, useState } from "react";
const ProductList = memo(function ProductList({ products }) {
console.log("ProductList rendered");
return (
<ul>
{products.map(product => (
<li key={product.id}>{product.name}</li>
))}
</ul>
);
});
function ProductPage() {
const [theme, setTheme] = useState(false);
const [count, setCount] = useState(0);
const products = useMemo(() => [
{ id: 1, name: "Laptop" },
{ id: 2, name: "Mobile" }
], []);
return (
<div style={{ background: theme ? "#ddd" : "#fff" }}>
<h2>Count: {count}</h2>
<button onClick={() => setCount(count + 1)}>
Increase Count
</button>
<button onClick={() => setTheme(!theme)}>
Change Theme
</button>
<ProductList products={products} />
</div>
);
}
export default ProductPage;
Explanation: The products array keeps the same reference between renders while the memoized value is retained. Because ProductList is wrapped in memo, it can skip re-rendering when its props have not changed.
Important: memo and useMemo are performance optimizations, not guarantees. A child may still render when its own state or context changes, and React may discard a memoized value in certain circumstances.
10. Difference Between useMemo and useCallback
Both Hooks use dependency arrays, but they cache different things.
| Feature |
useMemo |
useCallback |
| Purpose |
Caches the result of a calculation. |
Caches a function definition. |
| Returns |
The calculated value. |
The function itself. |
| Typical use |
Filtering, sorting, or expensive calculations. |
Passing a stable callback to an optimized child. |
| Syntax |
useMemo(() => calculate(), [value]) |
useCallback(() => handleClick(), [value]) |
useMemo Example
const total = useMemo(() => {
return price * quantity;
}, [price, quantity]);
useCallback Example
const handleClick = useCallback(() => {
console.log("Current count:", count);
}, [count]);
Remember: Use useMemo for a cached value and useCallback for a cached function definition.
11. useMemo vs. Calculating Directly
Not every calculation requires memoization. For simple operations, calculating the value directly is usually easier to read.
Without useMemo
function Price({ price, quantity }) {
const total = price * quantity;
return <p>Total: ₹{total}</p>;
}
With useMemo
function Price({ price, quantity }) {
const total = useMemo(() => {
return price * quantity;
}, [price, quantity]);
return <p>Total: ₹{total}</p>;
}
Both examples calculate the same total. For a simple multiplication, useMemo usually provides no meaningful benefit. It is better suited to expensive calculations or situations where a stable reference is useful.
12. Common useMemo Mistakes
| Mistake |
Problem |
Correct Approach |
| Using useMemo for every calculation |
Adds unnecessary complexity. |
Memoize when there is a measurable or practical benefit. |
| Missing dependencies |
The calculation may use outdated values. |
Include all reactive values used by the calculation. |
| Forgetting the dependency array |
The calculation runs on every render. |
Provide the dependency array when caching is needed. |
| Performing side effects inside useMemo |
The calculation is not pure and may run more than expected. |
Use event handlers or an appropriate effect for side effects. |
| Calling useMemo conditionally |
Breaks the Rules of Hooks. |
Call it at the top level of the component or custom Hook. |
| Forgetting to return a value |
The memoized result may be undefined. |
Return the calculated value. |
| Expecting useMemo to stop all renders |
It caches a calculation, not the entire component. |
Understand how state, props, context, and memoization interact. |
| Using it as permanent storage |
React may discard the cache in specific situations. |
Use state or a ref when persistent storage is required. |
13. Rules of the useMemo Hook
- Call
useMemo at the top level of a React function component or custom Hook.
- Do not call it inside loops, conditions, or nested functions.
- Pass a calculation function that returns the desired value.
- Include all reactive values used by the calculation in the dependency array.
- Keep the calculation pure and free of side effects.
- Use the cached result only as a performance optimization.
- Do not modify arrays or objects received from props or state while calculating a memoized value.
- Use React Developer Tools Profiler to investigate actual performance problems.
14. Understanding Strict Mode with useMemo
When React Strict Mode is enabled, React may call the calculation function twice during development to help identify impure calculations. One result is ignored. This extra check does not occur in the same way in production.
Example
const result = useMemo(() => {
console.log("Calculating result");
return numbers.reduce((sum, number) => sum + number, 0);
}, [numbers]);
The console message may appear twice during development when Strict Mode performs its checks. This does not necessarily mean that the dependency array is incorrect.
Best practice: Keep memoized calculations pure. Do not send API requests, update state, modify the DOM, or change external data inside a useMemo calculation.
15. Practical Project: Student Marks Calculator
Create a student marks application that calculates the average score and determines whether a student has passed. This example demonstrates memoizing a calculation based on an array of marks.
Complete Code
import { useMemo, useState } from "react";
function StudentMarks() {
const [marks, setMarks] = useState([80, 75, 90]);
const [studentName, setStudentName] = useState("Amit");
const average = useMemo(() => {
if (marks.length === 0) {
return 0;
}
const total = marks.reduce((sum, mark) => sum + mark, 0);
return total / marks.length;
}, [marks]);
const status = average >= 40 ? "Pass" : "Fail";
function addMarks() {
setMarks(currentMarks => [...currentMarks, 85]);
}
return (
<div>
<h2>Student Marks Calculator</h2>
<label>
Student Name:
<input
value={studentName}
onChange={event => setStudentName(event.target.value)}
/>
</label>
<p>Student: {studentName}</p>
<p>Marks: {marks.join(", ")}</p>
<p>Average: {average.toFixed(2)}</p>
<p>Result: {status}</p>
<button onClick={addMarks}>Add Marks</button>
</div>
);
}
export default StudentMarks;
Project Explanation
marks stores the student's scores.
studentName stores the student's name.
useMemo calculates the average using the marks array.
- The average is recalculated when the
marks dependency changes.
- Changing only the student's name does not require recalculating the average.
- The pass/fail status is a simple derived value, so it does not need its own state or an effect.
16. Performance Optimization Tips
- Start by writing simple, readable code.
- Use
useMemo for calculations that are expensive enough to affect responsiveness.
- Memoize derived arrays or objects when stable references help optimized child components.
- Avoid creating unnecessary effects that update state and cause chains of re-renders.
- Do not expect
useMemo to make the initial render faster; its main purpose is to skip repeated work on later renders.
- Measure performance in realistic conditions instead of assuming memoization is needed.
- Consider React Compiler, when enabled in your project, because it can automatically memoize values and functions and reduce the need for manual memoization.
17. Interview Questions and Answers
Q1. What is useMemo in React?
useMemo is a React Hook that caches the result of a calculation between renders while its dependencies remain unchanged.
Q2. What is memoization?
Memoization is an optimization technique that stores the result of a calculation and reuses it when the relevant inputs have not changed.
Q3. What does useMemo return?
It returns the calculated value, either by running the calculation function or reusing a cached result.
Q4. What is the purpose of the dependency array?
The dependency array specifies the reactive values used by the calculation. React compares them with the previous values to determine whether recalculation is necessary.
Q5. What happens when a dependency changes?
React reruns the calculation and returns the updated value.
Q6. What happens when the dependency array is empty?
The calculation normally runs during the initial render, and React can reuse the cached result during later renders while the cache is retained.
Q7. What is the difference between useMemo and useCallback?
useMemo caches a calculated value, whereas useCallback caches a function definition.
Q8. Does useMemo prevent a component from re-rendering?
No. It caches a calculation result. It can indirectly help an optimized child component skip re-rendering when a memoized prop remains unchanged.
Q9. Can useMemo be used for API calls?
No. useMemo is for pure calculations, not side effects such as API requests. API synchronization generally belongs in an appropriate effect or data-fetching solution.
Q10. Can useMemo be called inside a loop?
No. It must be called at the top level of a React function component or custom Hook.
Q11. Is useMemo always necessary?
No. Use it when it provides a practical performance benefit or a useful stable reference. Simple calculations can usually be performed directly.
Q12. What is the difference between useMemo and useState?
useMemo caches the result of a calculation, while useState stores state that can be updated to trigger a re-render.
18. Practice Exercises
- Create a component that calculates the square of a number using
useMemo.
- Build a product filter that filters items by name and price.
- Calculate a shopping cart total from an array of products.
- Create a student marks calculator that displays an average score.
- Use
useMemo to preserve an array reference passed to a child wrapped with memo.
- Find and correct a missing dependency in a memoized calculation.
- Identify a calculation that does not need
useMemo and simplify the code.
- Use React Developer Tools Profiler to investigate a slow calculation.
19. Quick Revision Checklist
- Understand the meaning of memoization.
- Know the syntax of
useMemo.
- Understand how dependency arrays control recalculation.
- Know how to optimize expensive calculations.
- Understand the difference between
useMemo and useCallback.
- Know how stable references can help memoized child components.
- Avoid unnecessary memoization.
- Keep calculation functions pure.
- Follow the Rules of Hooks.
- Measure performance before applying optimizations.
20. Conclusion
The useMemo Hook helps React applications avoid unnecessary repeated calculations by caching values between renders. It is useful for expensive computations, large-list filtering, and preserving references when working with optimized child components. For best results, include the correct dependencies, keep calculations pure, and use memoization only when it provides a real benefit.
Official React Documentation: React useMemo Hook | React memo | React useCallback Hook
Explore the Course: JustAcademy React JS Training Course | Register for React JS Course Demo