The useMemo Hook is used to memorize the result of a calculation so that React can reuse the previously calculated value when the dependencies have not changed.
useMemo can help avoid unnecessary
expensive calculations. It should be used when memoization provides a
real benefit, not for every calculation.
useMemo is a React Hook that memoizes a calculated value.
const result = useMemo(
() => calculateValue(),
[dependency]
);
React can reuse the memoized result when the dependencies remain unchanged.
Normally, JavaScript calculations inside a component run whenever the component renders.
If a calculation is expensive, repeatedly performing it may be unnecessary when its input values have not changed.
const result = expensiveCalculation(data);
useMemo can cache the result based on dependencies.
Import useMemo from React before using it.
import { useMemo } from "react";
You can also import it along with other React Hooks.
import {
useMemo,
useState
} from "react";
const value = useMemo(
() => {
return calculation;
},
[dependencies]
);
The first argument is a function that calculates the value. The second argument is the dependency array.
The value returned by useMemo is the result of the
calculation function.
const total = useMemo(
() => price * quantity,
[price, quantity]
);
The calculation runs again when price or
quantity changes.
The dependency array tells React which values the calculation depends on.
const total = useMemo(
() => price * quantity,
[price, quantity]
);
If the dependencies do not change between renders, React can reuse the previous result.
import { useMemo } from "react";
function Product() {
const price = 100;
const quantity = 5;
const total = useMemo(
() => price * quantity,
[price, quantity]
);
return (
<h2>
Total: ₹{total}
</h2>
);
}
export default Product;
useMemo is often demonstrated with state values.
const [number, setNumber] =
useState(10);
const square = useMemo(
() => number * number,
[number]
);
The square is recalculated when number changes.
An expensive calculation may take significant time or processing resources.
function expensiveCalculation(number) {
console.log("Calculating...");
let result = 0;
for(let i = 0; i < 1000000; i++) {
result += number * i;
}
return result;
}
Memoization can prevent this calculation from running unnecessarily when its inputs have not changed.
const result = useMemo(
() => expensiveCalculation(number),
[number]
);
The calculation depends on number, so
number is included in the dependency array.
A component can re-render because its state or props change. During a render, normal calculations in the component body can run again.
With useMemo, a memoized calculation can reuse its previous
result when its dependencies have not changed.
function App() {
const [count, setCount] =
useState(0);
const [number, setNumber] =
useState(5);
const square = useMemo(
() => number * number,
[number]
);
return (
<div>
<h2>
Count: {count}
</h2>
<h2>
Square: {square}
</h2>
<button
onClick={() =>
setCount(count + 1)
}
>
Increase Count
</button>
<button
onClick={() =>
setNumber(number + 1)
}
>
Increase Number
</button>
</div>
);
}
Suppose a memoized calculation depends only on number.
const square = useMemo(
() => number * number,
[number]
);
Changing an unrelated state value does not change the dependency
number, so the previous memoized result can be reused.
useMemo can be useful when filtering or transforming an
array is expensive.
const filteredStudents = useMemo(
() => students.filter(
student => student.active
),
[students]
);
const activeStudents = useMemo(
() => {
return students.filter(
student =>
student.status === "active"
);
},
[students]
);
The filtering operation is recalculated when the
students reference changes.
A search result can be memoized when filtering a large list.
const results = useMemo(
() => {
return students.filter(
student =>
student.name
.toLowerCase()
.includes(search.toLowerCase())
);
},
[students, search]
);
Both students and search are dependencies.
Sorting a large array can also be a calculation that you may choose to memoize.
const sortedStudents = useMemo(
() => {
return [...students].sort(
(a, b) =>
a.name.localeCompare(b.name)
);
},
[students]
);
The spread operator creates a new array instead of directly mutating the original array.
useMemo can also preserve the same object reference until
its dependencies change.
const userInfo = useMemo(
() => ({
name: name,
role: role
}),
[name, role]
);
The object is recreated when name or
role changes.
Objects and arrays are compared by reference in JavaScript. Creating a new object on every render creates a new reference.
const user = {
name: "Rahul"
};
If the same object reference is important for optimization, a
memoization technique such as useMemo may be useful.
| Normal Calculation | useMemo |
|---|---|
| Runs during each relevant render. | Can reuse a memoized result. |
| No dependency array. | Uses a dependency array. |
| Simple calculations are usually enough. | Useful for selected expensive calculations. |
| Easy to read. | Adds memoization complexity. |
| useMemo | useCallback |
|---|---|
| Memoizes a calculated value. | Memoizes a function reference. |
| Returns a value. | Returns a function. |
| Useful for expensive calculations. | Useful when function reference stability matters. |
const value = useMemo(
() => calculate(),
[data]
);
const handleClick = useCallback(
() => doSomething(),
[data]
);
It is important to understand that useMemo does not stop
the component itself from rendering.
It memoizes the result of a calculation so that React can reuse that value when appropriate.
const result = useMemo(
() => expensiveCalculation(data),
[data]
);
Not every calculation needs memoization.
const total = price + tax;
For a simple and inexpensive calculation, adding
useMemo may make the code more complicated without a
meaningful benefit.
const total = useMemo(
() => {
return price *
quantity *
discount;
},
[price, quantity, discount]
);
Every value used by the calculation that can change should be considered when defining dependencies.
Derived data is information calculated from existing state or props.
const totalMarks = useMemo(
() => {
return marks.reduce(
(total, mark) =>
total + mark,
0
);
},
[marks]
);
The total is derived from the marks array.
useMemo can be used inside a component to memoize
calculated data that is passed to another component.
const filteredProducts = useMemo(
() =>
products.filter(
product =>
product.price < 1000
),
[products]
);
return (
<ProductList
products={filteredProducts}
/>
);
import {
useMemo,
useState
} from "react";
function StudentSearch() {
const [search, setSearch] =
useState("");
const students = [
{ id: 1, name: "Rahul" },
{ id: 2, name: "Amit" },
{ id: 3, name: "Priya" }
];
const filteredStudents =
useMemo(
() => {
return students.filter(
student =>
student.name
.toLowerCase()
.includes(
search.toLowerCase()
)
);
},
[search]
);
return (
<div>
<input
value={search}
onChange={(e) =>
setSearch(e.target.value)
}
placeholder="Search student"
/>
{filteredStudents.map(
student => (
<p key={student.id}>
{student.name}
</p>
)
)}
</div>
);
}
export default StudentSearch;
The basic workflow of useMemo is:
Component Render
↓
useMemo()
↓
Check Dependencies
↓
┌─────┴─────┐
↓ ↓
Same Changed
↓ ↓
Reuse Calculate
Value Again
useMemo for calculations where memoization provides a useful benefit.useCallback when the goal is to memoize a function reference.useMemo memoizes the result of a calculation.useMemo does not prevent the component from rendering.useMemo returns a value, while useCallback memoizes a function.
Question: What is the main purpose of the
useMemo Hook?