React - Performance Optimizations

Overview

Estimated time: 25–35 minutes

Learn to avoid unnecessary re-renders and optimize expensive computations with memoization and stable references.

Learning Objectives

  • Use React.memo, useMemo, and useCallback appropriately.
  • Understand when re-renders happen and how to reduce them safely.

Prerequisites

  • Props & State, useEffect

Try it: Memoized list item

View source
const { useState, useMemo, memo } = React;
const Item = memo(function Item({ value }){ console.log('render item', value); return <li>{value}</li>; });
function App(){
  const [n, setN] = useState(0);
  const items = useMemo(() => ['A','B','C'], []);
  return (
    <div>
      <button onClick={() => setN(n+1)}>Increment {n}</button>
      <ul>{items.map(i => <Item key={i} value={i} />)}</ul>
    </div>
  );
}
ReactDOM.createRoot(document.getElementById('try-perf')).render(<App />);

Syntax primer

  • memo(Component): Skips re-render if props are shallow-equal.
  • useMemo(factory, deps): Caches computed value until deps change.
  • useCallback(fn, deps): Caches function identity until deps change.

Common pitfalls

  • Overusing memoization can add complexity for little gain—measure before optimizing.
  • Passing new object/array props every render defeats memo; stabilize with useMemo/useCallback.

Exercises

  1. Wrap a child component with React.memo and observe when it re-renders.
  2. Stabilize a callback with useCallback and verify fewer re-renders.

Checks for Understanding

  1. When is React.memo useful, and when is it unnecessary?
  2. Why can passing new object/array literals as props cause extra re-renders?
Show answers
  1. When child renders are costly and props usually don’t change; it’s unnecessary if children are cheap or props always change.
  2. Because shallow equality fails on new identities each render; stabilize with useMemo/useCallback.