Optimize React apps by: preventing unnecessary re-renders (memo, useMemo, useCallback), virtualizing long lists, code splitting routes/components, optimizing context usage, and using proper keys. Measure first with React DevTools Profiler.
Re-render Prevention:
React.memo() for component memoizationuseMemo() for expensive computationsuseCallback() for stable callbacksList Optimization:
Code Splitting:
Context Optimization:
Measuring:
import { memo, useMemo, useCallback, useState } from 'react';
// Memoized component - only re-renders when props change
const ExpensiveList = memo(function ExpensiveList({ items, onItemClick }) {
console.log('ExpensiveList rendered');
return (
<ul>
{items.map(item => (
<li key={item.id} onClick={() => onItemClick(item)}>
{item.name}
</li>
))}
</ul>
);
});
function App() {
const [count, setCount] = useState(0);
const [items] = useState([{ id: 1, name: 'Item 1' }]);
// Without useCallback, new function every render
// ExpensiveList re-renders even though items didn't change!
const handleClick = useCallback((item) => {
console.log('Clicked:', item);
}, []); // Stable reference
// Without useMemo, computed every render
const sortedItems = useMemo(() => {
console.log('Sorting items...');
return [...items].sort((a, b) => a.name.localeCompare(b.name));
}, [items]); // Only recompute when items change
return (
<div>
<button onClick={() => setCount(c => c + 1)}>Count: {count}</button>
{/* ExpensiveList doesn't re-render when count changes */}
<ExpensiveList items={sortedItems} onItemClick={handleClick} />
</div>
);
}