React Performance

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.