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)