DEV Community

Roshan singh
Roshan singh

Posted on

React.memo vs useMemo vs useCallback — Complete Guide

If you're learning React, you've probably heard these terms everywhere:

  • React.memo
  • useMemo
  • useCallback

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>;
}
Enter fullscreen mode Exit fullscreen mode

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 />
    </>
  );
}
Enter fullscreen mode Exit fullscreen mode

🔍 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>;
});
Enter fullscreen mode Exit fullscreen mode

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} />;
}
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

Output:

false
Enter fullscreen mode Exit fullscreen mode

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>;
});
Enter fullscreen mode Exit fullscreen mode

Even with React.memo,
Child STILL re-renders because:

oldFunction !== newFunction
Enter fullscreen mode Exit fullscreen mode

React thinks:

❌ Prop changed


✅ Solution Using useCallback

const handleClick = useCallback(() => {
  console.log("Clicked");
}, []);
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

✅ With useCallback

Render 1 → create function
Render 2 → reuse same function
Render 3 → reuse same function
Enter fullscreen mode Exit fullscreen mode

3️⃣ useMemo

✅ What is useMemo?

useMemo memoizes values or expensive calculations.


❌ Problem Without useMemo

const filteredUsers = users.filter(user => user.active);
Enter fullscreen mode Exit fullscreen mode

This runs:

🚨 On EVERY render

Even when unrelated state changes.


🤯 Example

Suppose:

  • theme changes
  • modal opens
  • input typing happens

Still:

users.filter()
Enter fullscreen mode Exit fullscreen mode

runs again.

For large data:
❌ performance issue.


✅ Solution Using useMemo

const filteredUsers = useMemo(() => {
  return users.filter(user => user.active);
}, [users]);
Enter fullscreen mode Exit fullscreen mode

Now calculation runs ONLY when:

users
Enter fullscreen mode Exit fullscreen mode

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}
/>
Enter fullscreen mode Exit fullscreen mode

Even with React.memo,
Child may STILL re-render because:

  • handleClick creates new function
  • filteredUsers creates new array/object

React sees:

oldProp !== newProp
Enter fullscreen mode Exit fullscreen mode

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.memo depends on stable references.
useMemo and useCallback help maintain those stable references.

Once this connection clicks, React rendering behavior becomes much easier to understand.

Top comments (0)