React.memo

How to prevent expensive child components from re-rendering unnecessarily when their parent re-renders.

React4 min readConcept 30 of 46

The Re-render Cascade

In React, when a component's state changes, it re-renders. By default, **all of its children will also re-render**, regardless of whether their props changed or not.

React assumes that if a parent changed, the children *might* need to change too, and rendering is usually fast enough that checking isn't worth the effort.

React.memo is a tool that tells React: 'Hey, this component is heavy. Only re-render it if its props actually change.'

When rendering is expensive

Imagine a Dashboard that has a simple text input (which updates state on every keystroke) and a massive Data Chart component (which takes 200ms to render).

Because the input is in the parent, typing in it causes the parent to re-render. This forces the heavy Data Chart to re-render on every single keystroke, causing severe lag.

By wrapping the Data Chart in React.memo, it will check its props. Since the charting data hasn't changed, it will skip the re-render entirely, keeping the input fast and snappy.

Wrapping your Component

To use it, you simply wrap your component definition in memo():

const ExpensiveChart = memo(function ExpensiveChart({ data }) { ... });

Now, when the parent re-renders, React will do a 'shallow comparison' of the old data prop and the new data prop. If they are identical (e.g., oldProps.data === newProps.data), the component will not re-render.

The Render Cascade

Interact with the Dashboard below. Notice how changing the unrelated count state forces the regular 'Heavy Component' to flash (re-render), while the 'Memoized Heavy Component' safely bails out.

function Parent() { const [count, setCount] = useState(0); const [theme, setTheme] = useState('light'); return ( <div className="parent"> {/* Both children take 'theme' as a prop */} <RegularHeavyChild theme={theme} /> <MemoizedHeavyChild theme={theme} /> </div> ); } // ❌ Re-renders every time Parent renders (even if count changes) function RegularHeavyChild({ theme }) { ... } // ✅ Only re-renders if 'theme' actually changes const MemoizedHeavyChild = React.memo( function MemoizedHeavyChild({ theme }) { ... } );

ParentComponent

state: count0
state: theme'light'
Regular
Heavy Child
prop: theme
Renders every time
Memoized
Heavy Child
prop: theme
Checks props first

Click 'Increment Count'. Notice how the Regular Child re-renders (flashes red) even though its 'theme' prop didn't change! The Memoized Child safely skips the render (blocks). When you toggle the Theme, both children re-render because the prop actually changed.

Check yourself

Pick an answer to lock it in, then read why. Getting one wrong is part of how it sticks.

  1. 1By default, what happens to a child component when its parent's state changes, but the props passed to the child remain exactly the same?
  2. 2What does `React.memo` actually do?
  3. 3If a component is wrapped in `React.memo`, but receives an inline object prop like `<UserCard user={{ name: 'John' }} />`, what will happen?

Remember this

  • By default, parent renders force all children to render.
  • React.memo prevents a component from rendering if its props haven't changed.
  • It only performs a 'shallow comparison' (using ===).
  • Passing new arrays, objects, or functions as props will break React.memo.
  • Don't wrap everything in memo; only use it for genuinely heavy components.

Done with this concept?

Mark it complete to track your progress. No login needed.