Skip to main content

memo() and state

What React.memo() does

React.memo() is a higher-order function (HOC) that "wraps" a functional component and tells React:

"If the props have not changed, do not re-render this component again."


Syntax

javascript
const MyComponent = React.memo(function MyComponent(props) { // ... });

or in arrow form:

javascript
const MyComponent = React.memo((props) => { // ... });

How React.memo() works

Normally React re-renders a component on every render of its parent, even if its props have not changed.

React.memo() does the following:

  1. Saves the component's previous props.
  2. On the next render, compares the new and old props (shallowly).
  3. If the props have not changed by reference -> the component does not re-render.
  4. If at least one prop has changed -> the component re-renders.

Without React.memo()

javascript
function Child({ value }) { console.log("Child re-render"); return <p>{value}</p>; } function Parent() { const [count, setCount] = useState(0); return ( <> <button onClick={() => setCount(c => c + 1)}>+</button> <Child value="static text" /> </> ); }

Every time you click, Parent re-renders, and Child re-renders too, even though its props do not change.


With React.memo()

javascript
const Child = React.memo(function Child({ value }) { console.log("Child re-render"); return <p>{value}</p>; });

Now Child does not re-render until its props (value) change.

Performance improves, especially with lists, tables, and large component trees.


How this relates to state

  1. When you call setState in the parent -> React re-renders the parent.
  2. By default all child components re-render too.
  3. React.memo() prevents these "unnecessary" re-renders if the child components do not depend on the parent's changed state.

Example

javascript
function Parent() { const [count, setCount] = useState(0); const [text, setText] = useState(""); return ( <div> <input value={text} onChange={e => setText(e.target.value)} /> <Counter count={count} /> <button onClick={() => setCount(c => c + 1)}>+</button> </div> ); } const Counter = React.memo(({ count }) => { console.log("Counter re-render"); return <p>Counter: {count}</p>; });

While typing, Counter does not re-render, because count (its prop) has not changed. Without React.memo(), a re-render would happen on every keystroke.


Important: shallow compare

React.memo() compares props by reference, not deeply.

Example:

javascript
const user = { name: "Tim" }; <Child data={user} />

If a new object is created on the next render:

javascript
<Child data={{ name: "Tim" }} />

React.memo will still re-render the component, because {} !== {} (different references in memory).

To avoid this, memoize objects and functions through:

javascript
useMemo() / useCallback()

Combining React.memo with useCallback / useMemo

React.memo is very often used together with memoized callbacks:

javascript
const handleClick = useCallback(() => { console.log("clicked"); }, []); // reference does not change between renders <Child onClick={handleClick} />

Without useCallback, React would create a new function on every render, and React.memo would not help, because the props would be "new" every time.


Summary

What React.memo() doesWraps a component so it re-renders only when props change
How it worksShallowly compares old and new props
Relation to statePrevents re-rendering of child components when the parent's state does not affect their props
Key tools nearbyuseCallback, useMemo - to keep stable references
When to useWith large trees, tables, lists, heavy child components
When not neededIn simple components - React is already optimized enough

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.