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
const MyComponent = React.memo(function MyComponent(props) {
// ...
});or in arrow form:
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:
- Saves the component's previous props.
- On the next render, compares the new and old props (shallowly).
- If the props have not changed by reference -> the component does not re-render.
- If at least one prop has changed -> the component re-renders.
Without React.memo()
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()
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
- When you call
setStatein the parent -> React re-renders the parent. - By default all child components re-render too.
React.memo()prevents these "unnecessary" re-renders if the child components do not depend on the parent's changed state.
Example
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:
const user = { name: "Tim" };
<Child data={user} />If a new object is created on the next render:
<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:
useMemo() / useCallback()Combining React.memo with useCallback / useMemo
React.memo is very often used together with memoized callbacks:
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() does | Wraps a component so it re-renders only when props change |
|---|---|
| How it works | Shallowly compares old and new props |
| Relation to state | Prevents re-rendering of child components when the parent's state does not affect their props |
| Key tools nearby | useCallback, useMemo - to keep stable references |
| When to use | With large trees, tables, lists, heavy child components |
| When not needed | In simple components - React is already optimized enough |
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.