← Back to React Course | Chapter 14: Performance & Production Deployment | Lesson 1 of 13

Why Performance Matters

React performance is like keeping a kitchen running smoothly during a dinner rush — you want dishes to come out fast without wasting effort recooking food nobody ordered again.

Measure Before Optimizing

It's tempting to sprinkle React.memo and useMemo everywhere out of habit, but this adds real complexity and can even hurt performance in some cases if used unnecessarily. The React DevTools Profiler lets you record an interaction and see exactly which components re-rendered and how long each took, pointing you at the ACTUAL bottleneck.

Note: Always profile first, then optimize the specific component the data actually points to — don't guess.

Warning: Optimizing components that aren't actually slow adds code complexity for zero real user-facing benefit.

Example: Measure Before Optimizing

markup
<!DOCTYPE html>
<html>
<head>
  <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
  <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
  <div id="root"></div>
  <script type="text/babel">
function App() {
  const [count, setCount] = React.useState(0);
  return <button onClick={() => setCount(count + 1)}>Count: {count} (Profile this with React DevTools)</button>;
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
  </script>
</body>
</html>

Re-rendering vs. Actual DOM Changes

When a component re-renders, React doesn't necessarily change anything in the actual browser DOM — it compares (diffs) the new virtual output against the previous one, and only applies the specific differences. A component re-rendering frequently isn't automatically a performance problem if the actual work involved is cheap.

Note: Frequent re-renders of small, simple components are often perfectly fine — focus performance attention on components doing genuinely expensive work.

Warning: Assuming 'this component re-renders often' automatically means 'this is a performance problem' can lead to optimizing things that were never actually slow.

Example: Re-rendering vs. Actual DOM Changes

markup
<!DOCTYPE html>
<html>
<head>
  <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
  <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
  <div id="root"></div>
  <script type="text/babel">
function Cheap({ value }) {
  return <span>{value}</span>; // re-rendering this is essentially free
}
function App() {
  const [tick, setTick] = React.useState(0);
  React.useEffect(() => { const id = setInterval(() => setTick(t => t + 1), 1000); return () => clearInterval(id); }, []);
  return <Cheap value={tick} />;
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
  </script>
</body>
</html>

Common, Real Sources of Slowness

The most frequent genuine performance issues are: expensive calculations repeated on every render (fixed by useMemo), functions/objects recreated every render breaking a child's memoization (fixed by useCallback/useMemo), and rendering very large lists without virtualization.

Note: Each of these has its own dedicated tutorial later in this chapter — this section is just the map of what to look for.

Warning: Apply the specific fix (useMemo, useCallback, React.memo, list virtualization) that matches the ACTUAL measured problem, not all of them defensively everywhere.

Example: Common, Real Sources of Slowness

markup
<!DOCTYPE html>
<html>
<head>
  <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
  <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
  <div id="root"></div>
  <script type="text/babel">
function App() {
  const items = Array.from({ length: 5 }, (_, i) => "Item " + i);
  // For huge lists (thousands of items), consider list virtualization
  // (a separate technique/library, not covered by useMemo/useCallback alone)
  return <ul>{items.map(i => <li key={i}>{i}</li>)}</ul>;
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
  </script>
</body>
</html>
Common Mistakes
  1. Optimizing prematurely, adding complexity (memoization everywhere) before actually measuring whether there's a real performance problem.
  2. Not using the React DevTools Profiler to identify which components are actually slow, guessing instead.
  3. Confusing re-rendering with 'the DOM actually changing' — React re-rendering a component doesn't necessarily mean the browser repaints anything, thanks to the virtual DOM diff.
Chapter Summary
  • Performance work should start with measuring (via the Profiler), not guessing which components are slow.
  • Common causes of slowness: unnecessary re-renders, expensive computations repeated every render, and large unoptimized lists/images.
  • React.memo, useMemo, and useCallback are targeted tools for specific re-render problems, not a default to apply everywhere.
  • Most apps don't need aggressive optimization — focus effort where profiling shows an actual, measurable problem.
Browser Support

No React-version restriction — React DevTools Profiler available for any React 16.5+ app.

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.