iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Performance

React performance work is mostly measuring before changing - the Profiler and DevTools tell you the truth that intuition gets wrong.

React performance toolkit

EXAMPLE
// 1. Measure with React DevTools Profiler
// In dev: open DevTools -> Profiler -> Record -> interact -> stop
// Read the flamegraph: which component re-rendered, why, how long

// 2. The actual rules
// - The default React renders a lot; that is OK
// - Only optimise the components you measured as slow
// - Premature memo and useMemo hurt readability and rarely help


// 3. Stable references - when memo actually pays off
import { memo, useCallback, useMemo } from 'react';

const Row = memo(function Row({ user, onSelect }: { user: User; onSelect: (id: string) => void }) {
  return <li onClick={() => onSelect(user.id)}>{user.name}</li>;
});

function List({ users }: { users: User[] }) {
  const onSelect = useCallback((id: string) => {
    /* ... */
  }, []);
  return <ul>{users.map((u) => <Row key={u.id} user={u} onSelect={onSelect} />)}</ul>;
}


// 4. Virtualise long lists
// npm install @tanstack/react-virtual
import { useVirtualizer } from '@tanstack/react-virtual';

function BigList({ items }: { items: any[] }) {
  const parentRef = useRef<HTMLDivElement>(null);
  const v = useVirtualizer({
    count: items.length,
    getScrollElement: () => parentRef.current,
    estimateSize: () => 40,
  });
  return (
    <div ref={parentRef} style={{ height: 600, overflow: 'auto' }}>
      <div style={{ height: v.getTotalSize(), position: 'relative' }}>
        {v.getVirtualItems().map((row) => (
          <div key={row.index} style={{ position: 'absolute', top: row.start, height: 40 }}>
            {items[row.index].name}
          </div>
        ))}
      </div>
    </div>
  );
}


// 5. Code split route components
const Settings = React.lazy(() => import('./Settings'));
// Wrap in <Suspense fallback={<Spinner />}>


// 6. Avoid unnecessary state in parents
// Move state down to leaves - small re-renders are cheap; big subtree re-renders are not.

// 7. React Compiler (RFC, stabilising) auto-memoises code
// Once stable, remove most useCallback/useMemo and let the compiler do the work.

// 8. Network is usually the bottleneck, not rendering
// - Cache with TanStack Query / SWR
// - Suspend on data fetching, not on UI
// - Reduce payloads server-side before reaching for React tricks

Why it matters

Measure first. The Profiler is right; your intuition is wrong. Most React perf wins come from virtualisation, code splitting, and smarter data fetching - not from sprinkling useMemo everywhere.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
// Profile with React DevTools. Wrap pure rows in React.memo.
// Use stable callbacks (useCallback) when passed to memoised children.
Try it Yourself »

Discussion

Loading…