React Performance Best Practices

In the last lesson, React Avoiding Unnecessary Re-renders, you learned the patterns for cutting wasted renders. This lesson pulls them into one performance best practices checklist, in the order you should actually apply them.

🤔 Why a checklist?

Here’s the pain. People optimize React by instinct, so they usually fix the wrong thing.

  • They add memo and useMemo everywhere, making code harder to read for no real gain.
  • They guess at what’s slow instead of measuring, so they fix things that were already fast.
  • They miss the simple structural fixes that would have solved it cleanly.

So this checklist puts the work in the right order: measure, fix structure, then memoize, and only where it matters.

📏 Measure first, always

The number one rule. Never optimize on a hunch. Find the real slow spot first.

  • Use the React DevTools Profiler to see which components render and how long they take.
  • Add a console.log in a component to count how often it renders.
  • Optimize only what the measurement shows is actually slow.

So prove where the problem is first. Most of the time the part you suspected was fine, and the real cause sits somewhere else.

Premature optimization hurts

Adding memoization everywhere “just in case” makes code harder to read and can even be slower, because the comparisons themselves cost time. Measure, then fix the real bottleneck. An app that’s already fast needs no optimization.

🪜 Apply fixes in the right order

When you do have a real problem, work through the fixes from simplest to most involved.

  • First, move state down so changes affect the smallest area.
  • Next, split big components and pass heavy content as children.
  • Then, React.memo on heavy children that still re-render needlessly.
  • Finally, useMemo and useCallback to keep object and function props stable for those memo children.

So structure first, memoization last. The simple structural fixes solve most problems, and with cleaner code too.

🔑 Keep list keys stable and unique

List keys are a subtle but real performance and correctness issue. The right key helps React update lists efficiently.

// ❌ index as key - causes bugs and extra work when the list reorders
{items.map((item, index) => <Row key={index} item={item} />)}
// ✅ a stable unique id - React tracks each item correctly
{items.map((item) => <Row key={item.id} item={item} />)}

Why this matters.

  • A stable id lets React match each item across renders and update only what changed.
  • Using the array index as a key confuses React when items are added, removed, or reordered, causing extra re-renders and sometimes wrong content.
  • So always prefer a real unique id over the index. Good keys aren’t just to silence a warning, they help React do the least work and keep lists correct.

💤 Lazy load what isn’t needed yet

Not everything needs to load at the start. Loading less upfront makes the first screen appear faster.

  • Split off big or rarely-used parts so they load only when needed.
  • React has React.lazy and Suspense for loading components on demand (you’ll see these in the patterns module).
  • A smaller initial bundle means the app shows up faster for the user, so load the heavy or rarely-used pieces later when they’re actually needed.

⚖️ Don’t over-optimize

It’s worth saying plainly: most React apps don’t need heavy optimization. React is fast by default.

  • Small components re-rendering is cheap; it’s not worth your time to stop.
  • Clean, simple code is usually fast enough and far easier to maintain.
  • Reach for optimization tools only when a measurement shows a real, heavy problem. Treat optimization as a targeted fix, not a default style, because readable code that’s fast enough beats clever code that’s hard to follow.

✅ Best Practices

Here’s the whole checklist in one place.

  • Measure first with the DevTools Profiler or console.log. Never guess.
  • Fix structure before memoizing: move state down, split components, use children.
  • Use React.memo on heavy children, with stable props from useMemo/useCallback.
  • Use stable, unique keys for lists, not the array index.
  • Lazy load big or rarely-used parts to speed up the first load.
  • Don’t over-optimize; most components are fine as plain code.

The golden order

Measure → restructure → memoize → only where it matters. If you remember nothing else from this module, remember that order. It keeps your app both fast and readable.

🧩 What You’ve Learned

  • ✅ Always measure first with the Profiler or console.log; never optimize on a hunch
  • ✅ Apply fixes in order: move state down, split components, then memo, then stable props
  • ✅ Use stable unique keys for lists, not the array index
  • ✅ Lazy load big or rarely-used parts to make the first screen appear faster
  • ✅ Don’t over-optimize; React is fast and most components are fine as plain code
  • ✅ The golden order is measure → restructure → memoize → only where it matters

Check Your Knowledge

Test what you learned. Pick an answer for each question, then click Check.

  1. 1

    What is the most important first step in React performance work?

    Why: Always measure with the Profiler or console.log before optimizing. Most of the time the suspected slow part is fine and the real cause is elsewhere.

  2. 2

    In what order should you apply performance fixes?

    Why: Structure first, memoization last. Moving state down and splitting components fix most problems with cleaner code; use memo and the hooks for what remains.

  3. 3

    Why prefer a stable unique id over the array index as a list key?

    Why: A unique id lets React match items across renders and update only what changed. Index keys cause extra work and bugs when items are added, removed, or reordered.

  4. 4

    What is the risk of over-optimizing with memoization?

    Why: Memoization has its own cost and clutters code. Adding it everywhere can be slower and harder to maintain. Apply it only where a measurement shows it helps.

🚀 What’s Next?

That wraps up the React Performance module. You can now measure, restructure, and memoize with intent. Next we move into advanced patterns that make your components more flexible and reusable, starting with compound components.

React Compound Components

Share & Connect