All skills
Skillintermediate

Performance Optimization

```tsx import { memo } from 'react';

Claude Code Knowledge Pack7/10/2026

Overview

Performance Optimization

React.memo


// Memoize component - only re-renders when props change
const ExpensiveList = memo(function ExpensiveList({ items }: { items: Item[] }) {
  return (
    <ul>
      {items.map(item => <li key={item.id}>{item.name}</li>)}
    </ul>
  );
});

// Custom comparison function
const UserCard = memo(
  function UserCard({ user }: { user: User }) {
    return <div>{user.name}</div>;
  },
  (prevProps, nextProps) => prevProps.user.id === nextProps.user.id
);

Preventing Re-renders

// Problem: New object/function on each render
function Parent() {
  // ❌ Creates new object every render
  return  doSomething()} />;
}

// Solution: Memoize or lift out
const style = { color: 'red' }; // Lifted out

function Parent() {
  const handleClick = useCallback(() => doSomething(), []);
  return ;
}

Code Splitting with lazy()


// Split heavy components
const HeavyChart = lazy(() => import('./HeavyChart'));
const AdminPanel = lazy(() => import('./AdminPanel'));

function App() {
  return (
    }>
      {showChart && }
    
  );
}

// Route-based splitting (React Router)
const routes = [
  {
    path: '/admin',
    element: (
      }>
        
      
    ),
  },
];

Virtualization


function VirtualList({ items }: { items: Item[] }) {
  const parentRef = useRef(null);

  const virtualizer = useVirtualizer({
    count: items.length,
    getScrollElement: () => parentRef.current,
    estimateSize: () => 50,
  });

  return (
    <div ref={parentRef} style={{ height: '400px', overflow: 'auto' }}>
      <div style={{ height: virtualizer.getTotalSize() }}>
        {virtualizer.getVirtualItems().map((virtualItem) => (
          <div
            key={virtualItem.key}
            style={{
              position: 'absolute',
              top: virtualItem.start,
              height: virtualItem.size,
            }}
          >
            {items[virtualItem.index].name}
          </div>
        ))}
      </div>
    </div>
  );
}

useMemo for Expensive Calculations

function Analytics({ data }: { data: DataPoint[] }) {
  // Only recalculate when data changes
  const stats = useMemo(() => ({
    total: data.reduce((sum, d) => sum + d.value, 0),
    average: data.reduce((sum, d) => sum + d.value, 0) / data.length,
    max: Math.max(...data.map(d => d.value)),
  }), [data]);

  return ;
}

useTransition for Non-urgent Updates


function Search() {
  const [query, setQuery] = useState('');
  const [results, setResults] = useState<Item[]>([]);
  const [isPending, startTransition] = useTransition();

  function handleChange(e: React.ChangeEvent) {
    setQuery(e.target.value); // Urgent: update input immediately

    startTransition(() => {
      // Non-urgent: can be interrupted
      setResults(filterItems(e.target.value));
    });
  }

  return (
    <>
      <input value={query} onChange={handleChange} />
      {isPending ?  : }
    </>
  );
}

Quick Reference

TechniqueWhen to Use
memo()Prevent re-renders from unchanged props
useMemo()Cache expensive calculations
useCallback()Stable function references
lazy()Code split heavy components
useTransition()Keep UI responsive during updates
VirtualizationLarge lists (1000+ items)
Anti-patternFix
Inline objectsLift out or useMemo
Inline functionsuseCallback
Large bundlelazy() + Suspense
Long listsVirtualization