πΉ 1. React.memo()
- What it is?
- A Higher-Order Component (HOC).
- Prevents a functional component from re-rendering if its props don’t change.
- When to use?
- For pure components that depend only on props.
- Good for performance optimization when child component is expensive to re-render.
β Example:
import React, { useState } from "react";
// Child component wrapped in React.memo
const Child = React.memo(({ name }) => {
console.log("Child rendered");
return <h3>Hello, {name} π</h3>;
});
function Parent() {
const [count, setCount] = useState(0);
return (
<div>
<button onClick={() => setCount(count + 1)}>
Increment: {count}
</button>
<Child name="Dev" /> {/* Child won't re-render when count changes */}
</div>
);
}
export default Parent;
π Here, even if count changes, Child won’t re-render because its props (name) didn’t change.
πΉ 2. useMemo()
- What it is?
- A React Hook.
- Caches the result of a function (value) until dependencies change.
- Prevents re-computing expensive calculations on every render.
- When to use?
- For expensive calculations or derived data inside a component.
β Example:
import React, { useState, useMemo } from "react";
function ExpensiveComponent() {
const [count, setCount] = useState(0);
const [number, setNumber] = useState(5);
// Expensive calculation (simulated with loop)
const factorial = useMemo(() => {
console.log("Calculating factorial...");
let result = 1;
for (let i = 1; i <= number; i++) {
result *= i;
}
return result;
}, [number]); // Recalculate only when number changes
return (
<div>
<button onClick={() => setCount(count + 1)}>Increment: {count}</button>
<button onClick={() => setNumber(number + 1)}>Increase Number</button>
<p>Factorial of {number} is {factorial}</p>
</div>
);
}
export default ExpensiveComponent;
π Here, factorial is cached and recalculated only when number changes, not when count changes.
πΉ Key Differences
| Feature | React.memo() π’ |
useMemo() π΅ |
|---|---|---|
| Type | Higher-Order Component | Hook |
| Purpose | Prevents re-rendering of component | Prevents re-calculation of values |
| Works On | Components | Functions / Expensive calculations |
| Optimization Level | Component-level re-rendering | Value/memoized result inside component |
| Example Use Case | Skip re-render of child component if props unchanged | Cache factorial, API result, filtered list |
πΉ Together Example (React.memo + useMemo)
import React, { useState, useMemo } from "react";
const List = React.memo(({ items }) => {
console.log("List rendered");
return <ul>{items.map((item, i) => <li key={i}>{item}</li>)}</ul>;
});
function App() {
const [count, setCount] = useState(0);
const [text, setText] = useState("");
const filteredList = useMemo(() => {
console.log("Filtering list...");
return ["apple", "banana", "orange"].filter((item) =>
item.includes(text)
);
}, [text]);
return (
<div>
<button onClick={() => setCount(count + 1)}>Increment {count}</button>
<input value={text} onChange={(e) => setText(e.target.value)} />
<List items={filteredList} />
</div>
);
}
export default App;
π Here:
useMemo()→ avoids re-filtering unlesstextchanges.React.memo()→ preventsListre-render unlessitemsactually change.
β Summary:
React.memo()→ skips re-render of a component.useMemo()→ skips re-computation of a value.- Both are performance optimizations, but solve different problems.