React.memo and Component Memoization
Prevent unnecessary re-renders with React.memo and proper memoization strategies
❌ Unoptimized Code
1// Problem: Component re-renders unnecessarily2const ExpensiveList = ({ items, filter, onItemClick }) => {3 console.log('ExpensiveList rendered'); // Logs too often45 const filteredItems = items.filter(item =>6 item.category === filter7 );89 return (10 <div>11 {filteredItems.map(item => (12 <div key={item.id} onClick={() => onItemClick(item)}>13 <img src={item.image} alt={item.name} />14 <h3>{item.name}</h3>15 <p>{item.description}</p>16 </div>17 ))}18 </div>19 );20};2122const Parent = () => {23 const [count, setCount] = useState(0);24 const [items] = useState(generateItems()); // Large array25 const [filter, setFilter] = useState('all');2627 const handleItemClick = (item) => {28 console.log('Item clicked:', item);29 };3031 return (32 <div>33 <p>Count: {count}</p>34 <button onClick={() => setCount(count + 1)}>Increment</button>35 <ExpensiveList36 items={items}37 filter={filter}38 onItemClick={handleItemClick}39 />40 </div>41 );42};
✅ Optimized Solution
1// Solution: Optimized with React.memo and memoization2const ExpensiveList = React.memo(({ items, filter, onItemClick }) => {3 console.log('ExpensiveList rendered');45 const filteredItems = useMemo(() => {6 console.log('Filtering items...');7 return items.filter(item =>8 filter === 'all' || item.category === filter9 );10 }, [items, filter]);1112 return (13 <div>14 {filteredItems.map(item => (15 <ExpensiveListItem16 key={item.id}17 item={item}18 onClick={onItemClick}19 />20 ))}21 </div>22 );23});2425const ExpensiveListItem = React.memo(({ item, onClick }) => {26 console.log('ExpensiveListItem rendered:', item.id);2728 return (29 <div onClick={() => onClick(item)}>30 <img src={item.image} alt={item.name} />31 <h3>{item.name}</h3>32 <p>{item.description}</p>33 </div>34 );35});3637const Parent = () => {38 const [count, setCount] = useState(0);39 const [items] = useState(generateItems);40 const [filter, setFilter] = useState('all');4142 const handleItemClick = useCallback((item) => {43 console.log('Item clicked:', item);44 }, []);4546 return (47 <div>48 <p>Count: {count}</p>49 <button onClick={() => setCount(count + 1)}>Increment</button>50 <ExpensiveList51 items={items}52 filter={filter}53 onItemClick={handleItemClick}54 />55 </div>56 );57};5859// Advanced: Custom comparison function60const ComplexComponent = React.memo(61 ({ data, metadata }) => {62 return (63 <div>64 <h2>{metadata.title}</h2>65 <p>{data.content}</p>66 </div>67 );68 },69 (prevProps, nextProps) => {70 // Only re-render if meaningful data changes71 return (72 prevProps.data.content === nextProps.data.content &&73 prevProps.metadata.title === nextProps.metadata.title74 );75 }76);
Performance Benefits
- ⚡Prevents unnecessary re-renders
- ⚡Improves performance for expensive components
- ⚡Reduces computational overhead
- ⚡Better user experience with smoother interactions