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)