Chapter 5: React Performance Optimization
Chapter 5 of 15
Chapter 5: React Performance Optimization
5.1 React.memo
React.memo is a higher-order component that memoizes the result of a component. It only re-renders if props have changed.
// Without memo - re-renders on every parent update
function ExpensiveComponent({ data }) {
// Expensive computation
const processed = processData(data);
return <div>{processed}</div>;
}
// With memo - only re-renders if props change
const MemoizedComponent = React.memo(function ExpensiveComponent({ data }) {
const processed = processData(data);
return <div>{processed}</div>;
});
// Custom comparison function
const MemoizedWithCustomCompare = React.memo(
ExpensiveComponent,
(prevProps, nextProps) => {
// Return true if props are equal (skip re-render)
return prevProps.data.id === nextProps.data.id;
}
);
5.2 useMemo and useCallback
useMemo memoizes expensive computations. useCallback memoizes functions to prevent unnecessary re-renders.
function ExpensiveComponent({ items, filter }) {
// useMemo - memoize expensive computation
const filteredItems = useMemo(() => {
return items.filter(item => item.category === filter);
}, [items, filter]);
// useCallback - memoize function
const handleClick = useCallback((id) => {
console.log('Clicked:', id);
}, []); // Empty deps - function never changes
return (
<div>
{filteredItems.map(item => (
<Item key={item.id} item={item} onClick={handleClick} />
))}
</div>
);
}
5.3 Virtualization
// Use react-window for large lists
import { FixedSizeList } from 'react-window';
function VirtualizedList({ items }) {
return (
<FixedSizeList
height={600}
itemCount={items.length}
itemSize={50}
width="100%"
>
{({ index, style }) => (
<div style={style}>
{items[index].name}
</div>
)}
</FixedSizeList>
);
}
5.4 Code Splitting
// Lazy load components
const LazyComponent = React.lazy(() => import('./LazyComponent'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
);
}