Performance: Avoiding unnecessary renders
This concept affects how fast the UI updates and how responsive the app feels during user interactions.
const Item = React.memo(function Item({ data }) { console.log('Render:', data.id); return <div>{data.name}</div>; }); function ItemList({ items }) { return items.map(item => <Item key={item.id} data={item} />); }
function ItemList({ items }) { return items.map(item => <Item key={item.id} data={item} />); } function Item({ data }) { console.log('Render:', data.id); return <div>{data.name}</div>; }
| Pattern | DOM Operations | Reflows | Paint Cost | Verdict |
|---|---|---|---|---|
| Without memoization | Many unnecessary DOM updates | Many reflows triggered | High paint cost due to frequent updates | [X] Bad |
| With React.memo | Only necessary DOM updates | Minimal reflows | Lower paint cost with fewer updates | [OK] Good |
React.memo in a React component?useCallback in React?const MyComponent = React.memo(({ count, onClick }) => {
console.log('Rendered');
return <button onClick={onClick}>Count: {count}</button>;
});
function App() {
const [count, setCount] = React.useState(0);
const handleClick = () => setCount(count + 1);
return <MyComponent count={count} onClick={handleClick} />;
}App re-renders?onClick is a new function each render.handleClick is recreated on every render, its reference changes, causing MyComponent to re-render.handleClick is recreated on each render -> Option Bconst Parent = () => {
const [count, setCount] = React.useState(0);
const increment = () => setCount(count + 1);
return <Child onClick={increment} />;
};
const Child = React.memo(({ onClick }) => {
console.log('Child rendered');
return <button onClick={onClick}>Click</button>;
});Child?increment function is recreated on every render, changing its reference and causing Child to re-render.increment in useCallback with count dependency keeps the same function reference unless count changes.increment in useCallback with count as dependency -> Option APass the test and this pattern moves unknown