DEV Community

Sachin Maurya
Sachin Maurya

Posted on

React Memoization: `React.memo`, `useCallback`, and `useMemo` Explained with Real Use Cases

🧠 Introduction

Ever noticed your React component re-rendering even when nothing seems to have changed? Or a table, chart, or dropdown becoming sluggish when the parent component updates frequently?

This is where React memoization comes to the rescue.

In this post, we’ll explore the three main tools React offers to avoid unnecessary re-renders and optimize performance:

  • React.memo
  • useCallback
  • useMemo

And instead of just theory, I’ll share real examples from my own experience on when to use them — and when to avoid them.


🔁 React.memo – Skip Re-renders for Pure Components

React.memo is a higher-order component that wraps around your functional component and skips re-rendering it if props haven’t changed.

Use it for:

  • Presentational components
  • Cards, tables, list items
  • Any component that receives stable props

Example:

const UserCard = React.memo(({ name }) => {
  console.log("Rendering:", name);
  return <div>{name}</div>;
});
Enter fullscreen mode Exit fullscreen mode

Even if the parent re-renders, UserCard won’t re-render unless the name prop changes.


🧠 useMemo – Cache Expensive Calculations

useMemo is ideal when you have a heavy computation or derived value that doesn’t need to be recalculated every render.

Use it for:

  • Filtering or sorting large arrays
  • Deriving values from props or state
  • Avoiding expensive recalculations

Example:

const sortedList = useMemo(() => {
  return items.sort((a, b) => a.value - b.value);
}, [items]);
Enter fullscreen mode Exit fullscreen mode

Without useMemo, items.sort() would run on every render, even if items didn’t change.


🪝 useCallback – Memoize Functions

When you pass functions as props to a memoized child component, they can cause unnecessary re-renders if recreated every render.

useCallback returns the same function instance unless dependencies change.

Example:

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

⚠️ When Not to Use Memoization

Optimization is powerful, but don’t overdo it.

Avoid using React.memo, useMemo, or useCallback if:

  • Components are small and cheap to render
  • Props or state change frequently anyway
  • It adds unnecessary complexity

Rule: Profile first, optimize second.


✅ Real-World Case

Recently, I had a dynamic form with multiple inputs and dropdowns.

Whenever the parent updated (like from a context), the entire form re-rendered, making it slow.

Solution:

  • Wrapped each field block with React.memo
  • Memoized dropdown options using useMemo
  • Used useCallback for onChange handlers

Result:
Reduced render count by ~40%, resulting in a much smoother experience.


📚 Key Takeaways

Tool Use Case
React.memo Prevent re-rendering of child components if props haven’t changed
useMemo Cache computed values
useCallback Cache functions passed to children

🧠 Final Thoughts

Memoization is like salt — a little can enhance the experience, too much can ruin it.

Use the React DevTools Profiler to identify where optimization is needed, then memoize with intent.

Top comments (0)