If you're learning React, you've probably heard these terms everywhere:
React.memouseMemouseCallback
At first, they look confusing.
But all three solve one major problem:
⚡ Unnecessary Re-renders & Performance Issues
This guide explains:
- what each one does
- why they exist
- how they are connected
- when to use them
- interview explanations
🤔 Why Do These Exist?
In React, components re-render very frequently.
A component re-renders when:
- state changes
- props change
- parent component re-renders
Most of the time this is fine.
But in large applications:
- expensive calculations
- recreated functions
- unnecessary child renders
can slow down the application.
That’s why React provides:
- React.memo
- useMemo
- useCallback
for optimization.
🧠 First Understand One Important Thing
In React:
function App() {
console.log("Rendered");
return <h1>Hello</h1>;
}
Whenever React re-renders:
- the ENTIRE component function runs again
- variables get recreated
- functions get recreated
This is the root reason why memoization exists.
1️⃣ React.memo
✅ What is React.memo?
React.memo prevents unnecessary component re-renders.
❌ Problem Without React.memo
function Child() {
console.log("Child rendered");
return <h1>Child Component</h1>;
}
function Parent() {
const [count, setCount] = useState(0);
return (
<>
<button onClick={() => setCount(count + 1)}>
Increment
</button>
<Child />
</>
);
}
🔍 What Happens Here?
When button is clicked:
- Parent re-renders
- Child ALSO re-renders
Even though:
- Child props didn't change
- Child state didn't change
❌ This is an unnecessary re-render.
✅ Solution Using React.memo
const Child = React.memo(() => {
console.log("Child rendered");
return <h1>Child Component</h1>;
});
Now React remembers the previous render.
If props are unchanged:
✅ Child render is skipped
⚙️ How React.memo Works Internally
React performs:
👉 Shallow Comparison
It compares:
- old props
- new props
If props are same:
✅ React skips rendering.
📌 Important Point
React.memo works best with:
- strings
- numbers
- booleans
But NOT always with:
- functions
- arrays
- objects
Because they create new references every render.
That’s where useCallback and useMemo help.
2️⃣ useCallback
✅ What is useCallback?
useCallback memoizes functions.
It prevents function recreation on every render.
❌ Problem Without useCallback
function Parent() {
const [count, setCount] = useState(0);
const handleClick = () => {
console.log("Clicked");
};
return <Child onClick={handleClick} />;
}
Looks normal, right?
But here's the hidden issue:
🚨 A NEW function gets created on every render
🤯 Why?
Because in JavaScript:
const a = () => {};
const b = () => {};
console.log(a === b);
Output:
false
Because:
- both functions have different memory references
🚨 Why This Causes Re-renders
Suppose Child uses:
const Child = React.memo(({ onClick }) => {
console.log("Child rendered");
return <button onClick={onClick}>Click</button>;
});
Even with React.memo,
Child STILL re-renders because:
oldFunction !== newFunction
React thinks:
❌ Prop changed
✅ Solution Using useCallback
const handleClick = useCallback(() => {
console.log("Clicked");
}, []);
Now React stores:
✅ SAME function reference
between renders.
So:
- Child gets same prop
- React.memo works properly
- unnecessary render avoided
🧠 Behind The Scenes
❌ Without useCallback
Render 1 → new function
Render 2 → new function
Render 3 → new function
✅ With useCallback
Render 1 → create function
Render 2 → reuse same function
Render 3 → reuse same function
3️⃣ useMemo
✅ What is useMemo?
useMemo memoizes values or expensive calculations.
❌ Problem Without useMemo
const filteredUsers = users.filter(user => user.active);
This runs:
🚨 On EVERY render
Even when unrelated state changes.
🤯 Example
Suppose:
- theme changes
- modal opens
- input typing happens
Still:
users.filter()
runs again.
For large data:
❌ performance issue.
✅ Solution Using useMemo
const filteredUsers = useMemo(() => {
return users.filter(user => user.active);
}, [users]);
Now calculation runs ONLY when:
users
changes.
⚙️ How useMemo Works Internally
React stores:
- previous dependencies
- previous calculated value
If dependencies don't change:
✅ Cached value is returned
No recalculation happens.
🔥 MOST IMPORTANT — How All Three Are Connected
This is where most beginners get confused.
❌ React.memo Alone Is NOT Enough
Suppose:
<Child
onClick={handleClick}
data={filteredUsers}
/>
Even with React.memo,
Child may STILL re-render because:
-
handleClickcreates new function -
filteredUserscreates new array/object
React sees:
oldProp !== newProp
because references changed.
✅ That’s Why We Need:
👉 useCallback
to preserve function reference
AND
👉 useMemo
to preserve value/object/array reference
So that:
✅ React.memo can ACTUALLY skip rendering
🧩 Simple Mental Model
✅ React.memo
“Skip component render if props are same.”
✅ useCallback
“Keep same function reference.”
✅ useMemo
“Keep same calculated value/reference.”
📊 Final Difference Between All Three
| Feature | React.memo | useMemo | useCallback |
|---|---|---|---|
| Used For | Component | Value | Function |
| Prevents | Re-render | Recalculation | Function recreation |
| Returns | Memoized component | Memoized value | Memoized function |
| Common Use | Child optimization | Expensive calculations | Stable callbacks |
🚫 When NOT To Use Them
Do NOT overuse memoization.
These hooks also have overhead.
Use them only when:
- unnecessary renders are causing issues
- calculations are expensive
- components are large/heavy
🎯 Interview Summary
✅ React.memo
Prevents unnecessary component re-renders using shallow prop comparison.
✅ useMemo
Memoizes calculated values and recalculates only when dependencies change.
✅ useCallback
Memoizes function references to prevent unnecessary function recreation and child re-renders.
🏁 Final Thoughts
Most developers memorize:
- syntax
- definitions
But the REAL understanding is:
React.memodepends on stable references.
useMemoanduseCallbackhelp maintain those stable references.
Once this connection clicks, React rendering behavior becomes much easier to understand.
Top comments (0)