By default, when a parent component re-renders in React, all of its child components automatically re-render as well—even if the child's props haven't changed.
React.memo is a higher-order component (HOC) that memoizes rendering results. If a component's props remain unchanged between renders, React skips rendering the component and reuses the previous rendered output.
flowchart TD
Parent["Parent Re-renders"] --> Child["Child wrapped in React.memo(Child)"]
Child --> Check{"Have Props Changed?"}
Check -- Yes --> Render["Re-render Child Component"]
Check -- No --> Skip["Skip Render & Reuse Cached Virtual DOM"]
import React, { useState, memo } from 'react';
// Memoized Expensive Component
const ExpensiveChild = memo(function ExpensiveChild({ count }) {
console.log('ExpensiveChild rendered!');
return (
<div className="memo-box">
<h3>Memoized Count: {count}</h3>
</div>
);
});
export default function ParentController() {
const [persistentCount, setPersistentCount] = useState(0);
const [text, setText] = useState('');
return (
<div className="parent-box">
<h2>React.memo Performance Demo</h2>
{/* Typing here triggers ParentController re-render */}
<input
type="text"
value={text}
onChange={(e) => setText(e.target.value)}
placeholder="Type here..."
/>
<button onClick={() => setPersistentCount(prev => prev + 1)}>
Increment Child Count
</button>
{/* ExpensiveChild will NOT re-render when typing in the input box */}
<ExpensiveChild count={persistentCount} />
</div>
);
});
By default, React.memo performs shallow prop comparison. You can supply a custom comparison function as a second argument for deep or tailored property comparisons:
function arePropsEqual(prevProps, nextProps) {
return prevProps.item.id === nextProps.item.id;
}
export default memo(MyComponent, arePropsEqual);
React.memo only for components that render frequently with heavy sub-trees or large lists.style={{ color: 'red' }}) or inline arrow functions (onClick={() => ...}) creates new object references on every parent render, invalidating shallow prop comparison. Combine React.memo with useCallback and useMemo.Explain why passing an unmemoized callback function onClick={handleClick} as a prop to a React.memo child causes the child to re-render despite wrapping it in React.memo.
Sign in to track your learning journey, earn industry-recognized certificates, and join our elite developer community.
Quick Access With