React Performance
React is fast by default, but as your app grows you’ll encounter components that render too often or take too long. Here are the key tools.
useMemo โ Expensive Computations
function FilteredList({ items, query, sortBy }) {
// Without useMemo: filters and sorts on EVERY render (even unrelated ones)
// With useMemo: only recomputes when items, query, or sortBy changes
const result = useMemo(() => {
console.log("Computing filtered list...");
return items
.filter(item => item.name.toLowerCase().includes(query.toLowerCase()))
.sort((a, b) => sortBy === "price"
? a.price - b.price
: a.name.localeCompare(b.name)
);
}, [items, query, sortBy]);
return <ul>{result.map(i => <li key={i.id}>{i.name}</li>)}</ul>;
}
Code Splitting & Lazy Loading
import { lazy, Suspense } from "react";
// The component is loaded ONLY when first needed โ not in the initial bundle
const HeavyDashboard = lazy(() => import("./pages/Dashboard"));
const PDFViewer = lazy(() => import("./components/PDFViewer"));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<Routes>
<Route path="/dashboard" element={<HeavyDashboard />} />
</Routes>
</Suspense>
);
}
List Virtualisation
npm install react-window
import { FixedSizeList } from "react-window";
function VirtualList({ items }) {
// Renders only the ~10 visible rows โ not all 10,000
const Row = ({ index, style }) => (
<div style={style} className="list-row">
{items[index].name}
</div>
);
return (
<FixedSizeList
height={500} // px height of the visible window
itemCount={items.length}
itemSize={50} // px height of each row
width="100%"
>
{Row}
</FixedSizeList>
);
}
Performance Checklist
| Technique | When to apply |
|---|---|
| React.memo | Expensive pure component that receives stable props |
| useCallback | Function passed as prop to a memoised child |
| useMemo | Filtering/sorting large datasets on every render |
| code splitting | Routes or components > 50KB not needed at startup |
| Virtualisation | Lists with > 100 items |
| Image optimisation | Use WebP, lazy loading, correct dimensions |
TipOpen React DevTools โ Profiler tab โ Record โ interact โ Stop. Look for components with long render bars. Fix what you can measure โ don’t guess.