gotchajavascriptreactModerate
React.memo doesn't prevent re-renders from new object/array props
Viewed 0 times
React 16.6+ for React.memo
React.memouseMemouseCallbackshallow comparisonre-render optimizationreference equality
browser
Problem
Wrapping a component in React.memo but passing inline objects, arrays, or functions as props still causes re-renders. memo does shallow comparison — new references (even with same content) are 'different'.
Solution
Memoize props with useMemo/useCallback:
// Parent component
function Parent() {
const [count, setCount] = useState(0);
// BAD: new object every render defeats memo
// <Child style={{ color: 'red' }} />
// GOOD: stable reference
const style = useMemo(() => ({ color: 'red' }), []);
const handleClick = useCallback(() => doSomething(), []);
return <Child style={style} onClick={handleClick} />;
}
const Child = React.memo(function Child({ style, onClick }) {
return <div style={style} onClick={onClick}>...</div>;
});
// Or use a custom comparison function
const Child = React.memo(Component, (prevProps, nextProps) => {
return prevProps.id === nextProps.id; // only re-render if id changes
});
// Parent component
function Parent() {
const [count, setCount] = useState(0);
// BAD: new object every render defeats memo
// <Child style={{ color: 'red' }} />
// GOOD: stable reference
const style = useMemo(() => ({ color: 'red' }), []);
const handleClick = useCallback(() => doSomething(), []);
return <Child style={style} onClick={handleClick} />;
}
const Child = React.memo(function Child({ style, onClick }) {
return <div style={style} onClick={onClick}>...</div>;
});
// Or use a custom comparison function
const Child = React.memo(Component, (prevProps, nextProps) => {
return prevProps.id === nextProps.id; // only re-render if id changes
});
Why
React.memo shallow-compares each prop. {} === {} is false in JavaScript — every render creates new objects even if the content is identical. useMemo and useCallback return the same reference across renders when dependencies haven't changed.
Gotchas
- Don't overuse memo/useMemo/useCallback — they have overhead too
- Primitive props (strings, numbers, booleans) are compared by value — always stable
- Children prop is often a new JSX object — this defeats memo
- Profile first, optimize second — most re-renders are fine
Code Snippets
Stable props for memoized components
// Stable references prevent memo re-renders
const config = useMemo(() => ({ theme: 'dark' }), []);
const onClick = useCallback(() => save(), [save]);
<MemoizedChild config={config} onClick={onClick} />Context
When optimizing React component re-renders with memo
Revisions (0)
No revisions yet.