#  7 Ways to Speed Up Your React App


Performance work on a React app tends to start with the flashiest-sounding optimization (memoization) instead of the ones that usually have the biggest actual impact. Here's a more accurate priority order.

**1. Code splitting — load less JavaScript upfront**

```javascript
// Instead of importing everything eagerly
import Dashboard from './Dashboard';

// Load it only when actually needed
const Dashboard = lazy(() => import('./Dashboard'));
```

The single biggest lever for initial load time is usually shipping less JavaScript on first load, not making the JavaScript that runs faster. A route the user never visits shouldn't be in their initial bundle.

**2. Virtualize long lists**

Rendering 1,000 DOM nodes for a list where only 10 are visible on screen at once wastes rendering time on invisible elements. Libraries like `react-window` or `react-virtual` render only what's actually in the viewport, plus a small buffer.

```javascript
import { FixedSizeList } from 'react-window';

<FixedSizeList height={400} itemCount={1000} itemSize={35}>
  {({ index, style }) => <div style={style}>Row {index}</div>}
</FixedSizeList>
```

This matters far more than memoization for any list beyond roughly a hundred items.

**3. Image optimization — often the biggest actual payload**

Unoptimized images are frequently the single largest contributor to page weight, dwarfing your JavaScript bundle. Modern formats (WebP, AVIF), proper sizing (not shipping a 4000px image displayed at 400px), and lazy loading (`loading="lazy"`) for below-the-fold images typically move the needle more than any React-specific optimization.

**4. Debounce expensive operations tied to user input**

```javascript
const debouncedSearch = useMemo(
  () => debounce((query) => searchAPI(query), 300),
  []
);
```

If an expensive operation (an API call, a heavy filter/sort) runs on every keystroke, debouncing it fixes a real, felt performance issue — often more impactful than memoizing the render itself.

**5. Fix unnecessary re-renders (the Day 3 topic, applied here)**

`React.memo` + stable function references via `useCallback`, applied specifically where the Profiler shows an actual problem — not applied everywhere by default. This is real, but it's #5 on this list, not #1, because it usually matters less than the previous four for overall perceived speed.

**6. Use `useMemo` for genuinely expensive calculations only**

```javascript
// Worth memoizing: an actually expensive computation
const sorted = useMemo(() => expensiveSort(largeArray), [largeArray]);

// Not worth memoizing: trivial calculations
const total = useMemo(() => a + b, [a, b]); // just calculate it directly
```

`useMemo` has its own small cost (storing and comparing the cached value) — applying it to cheap calculations can net negative, not neutral.

**7. Move state down, not up**

State that only affects a small subtree shouldn't live at the top of your component tree — that forces the entire tree to re-render when it changes. Keeping state as close as possible to where it's actually used limits the blast radius of each state update.

```javascript
// If only the input needs this state, keep it in the input's component,
// not lifted to a parent that renders a large unrelated subtree
```

**Why the order matters**

Items 1-3 (code splitting, list virtualization, image optimization) typically move perceived load time and scroll performance the most, for the least implementation risk. Items 5-6 (memoization) get reached for first in most advice, despite usually having smaller real-world impact and genuine risk of misuse (stale closures, unnecessary complexity) if applied without profiling first.

**Try this yourself:** open your app in Chrome DevTools' Performance or Lighthouse tab before making any changes, and note the actual numbers (bundle size, largest contentful paint, total blocking time). Fix one item from this list, re-measure, and compare. Guessing which optimization mattered is far less reliable than actually measuring it.

**Takeaway:** React performance work should start with what users actually feel — load time, scroll smoothness, input responsiveness — not with the optimization that sounds most technically sophisticated. Code splitting and image optimization usually move the needle more than memoization ever will.
