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
- Wrap a child component with React.memo and observe when it re-renders.
- Stabilize a callback with useCallback and verify fewer re-renders.
Checks for Understanding
- When is
React.memo
useful, and when is it unnecessary? - Why can passing new object/array literals as props cause extra re-renders?
Show answers
- When child renders are costly and props usually don’t change; it’s unnecessary if children are cheap or props always change.
- Because shallow equality fails on new identities each render; stabilize with
useMemo
/useCallback
.