React.memo vs useCallback vs useMemo

A Beginner-Friendly Guide to Preventing Unnecessary Re-Renders in React

Thumbnail Image

If you’ve been building apps with React for a while, you’ve probably noticed something interesting: when a parent component updates, its children update too — even if nothing actually changed for them.

This can feel confusing at first.

So the big question is:

👉 If a parent re-renders, how do we stop the child from re-rendering when nothing changed for the child?

Let’s break this down step by step, simply and practically.

To read more article on React visit here

First, Understand This Core Rule

By default in React, when a parent component re-renders, all of its children re-render as well.

Even if:

  • The child receives no props
  • The child has no state
  • The UI output would look exactly the same

React still calls the child function again.

This is normal behaviour.

Example: Why Is the Child Re-Rendering?

Let’s look at a simple example.

function Parent() {
const [count, setCount] = React.useState(0);
return (
<>
<button onClick={() => setCount(count + 1)}>
Increase
</button>
<Child />
</>

);
}

function Child() {
console.log("Child rendered");
return <h1>I am child</h1>;
}

Now click the button.

Even though Child:

  • Doesn’t use count
  • Has no props
  • Has no state

It still re-renders.

Why? Because when Parent updates, React re-evaluates its children too.

Solution 1: React.memo

The most common way to prevent unnecessary child re-renders is by using React.memo.

It tells React:

“Only re-render this component if its props change.”

Here’s the fix:

const Child = React.memo(function Child() {
console.log("Child rendered");
return <h1>I am child</h1>;
});

Now what happens?

  • Click button → Parent re-renders
  • Child does NOT re-render

Because the child’s props didn’t change.

Simple and powerful.

Important: React.memo Only Checks Props

React.memo performs a shallow comparison of props.

This works fine:

<Child name="Rahul" />

But this can cause problems:

<Child data={{ name: "Rahul" }} />

Why?

Because every render creates a new object in memory.

Even if the content is the same, the reference is different. React sees a new object and assumes the prop changed — so it re-renders.

This is where useMemo and useCallback Come in.

Solution 2: useCallback (For Functions)

Functions are recreated every time a component renders.

For example:

<Child onClick={() => console.log("Hi")} />

That arrow function is new on every render.

Even if it Child is wrapped inReact.memo, it will still re-render because the function reference changes.

Fix It with useCallback

const handleClick = React.useCallback(() => {
console.log("Hi");
}, []);
<Child onClick={handleClick} />

Now the function reference stays stable.

If props don’t change, the child won’t re-render.

Use useCallback when:

  • You pass functions to memoised children
  • You want a stable function reference

Solution 3: useMemo (For Objects and Arrays)

Objects and arrays also get recreated on every render.

Example:

<Child config={{ theme: "dark" }} />

That object is new every time.

Fix It with useMemo

const config = React.useMemo(() => ({
theme: "dark"
}), []);
<Child config={config} />

Now the object reference stays the same.

Use useMemo when:

  • Passing objects or arrays as props
  • Performing expensive calculations

Clean Mental Model

Here’s the simple flow to remember:

Parent re-renders
→ React re-evaluates children
→ If child is wrapped in React.memo
→ React shallow-compares props
→ If props are the same → Skip render
→ If props changed → Re-render

That’s it.

Important Reality Check

Before you start wrapping everything in React.memo, pause.

Re-rendering:

  • Does NOT automatically mean DOM updates
  • Is usually very fast
  • Is completely normal in React

React still compares the virtual DOM and avoids real DOM updates if nothing changed visually.

So optimise only when:

  • The component is heavy
  • Rendering is expensive
  • Performance profiling shows a problem

Premature optimisation can make your code harder to read without real benefit.

How to Verify Re-Renders

If you want to confirm whether something is re-rendering:

Add this inside the component:

console.log("Child rendered");

Or use React DevTools and enable update highlighting.

Measure first. Then optimize.

🚀 Advanced Note

Keep in mind:

React.memo works only for:

  • Functional components
  • Props comparison

It does NOT prevent re-rendering if:

  • The component’s internal state changes
  • Context value changes

So it’s not a magic shield — it’s a smart optimisation tool.

Final Takeaways

Here’s the quick summary:

  • By default, child components re-render when the parent re-renders.
  • Use React.memo to skip re-renders when props don’t change.
  • Use useCallback to stabilize function props.
  • Use useMemo to stabilize object or array props.
  • Optimize only when performance actually requires it.

Mastering these three tools gives you better control over rendering behaviour — and helps you write more efficient, predictable React applications.

Did you enjoy reading it?

I truly appreciate you taking the time to read this guide. I hope it helped you understand Redux and its core concepts with more clarity and confidence.

If you found it helpful, feel free to share it with others who are learning React and state management. Your support means a lot.

More practical and beginner-friendly content is on the way — stay connected. 🚀

At Dev Simplified, We Value Your Feedback 📊

👉 To read more articles on React, visit here

👉 Follow us not to miss any updates.

👉 Have any suggestions? Let us know in the comments!

👉 Subscribe for free and join our growing community!