useMemo & useCallback
Optimise performance by avoiding unnecessary recalculations and re-creations.
What you will learn
- Memoise expensive values with useMemo
- Memoise functions with useCallback
- Know when optimisation is worth it
Avoid redoing expensive work
useMemo remembers a computed value and only recalculates it when its dependencies change. useCallback does the same for functions.
// Only recompute when 'numbers' changes
const total = useMemo(() => {
return numbers.reduce((sum, n) => sum + n, 0);
}, [numbers]);
// Keep the same function reference between renders
const handleClick = useCallback(() => {
doSomething(id);
}, [id]);Normally a component re-runs all its code on every render. These two hooks let React skip repeating work when nothing it depends on has changed:
useMemo—useMemo(() => numbers.reduce(...), [numbers])runs the calculation and remembers the result. On the next render, ifnumbersis the same as before, React hands back the savedtotalinstead of adding everything up again. It only recalculates whennumbers(the dependency) actually changes.useCallback—useCallback(() => doSomething(id), [id])remembers the function itself, so React gives you the exact same function each render (instead of creating a fresh one). This matters when you pass a function down to a child that is optimised to skip re-rendering when its props have not changed.
Note: Think of the dependency array as “only redo this when one of these values changes”. With [numbers], the total is recomputed only when numbers changes; with [id], the function is rebuilt only when id changes.
A concrete walk-through with real values. Say numbers is [10, 20, 30], so useMemo runs the calculation once and stores total = 60:
- The component re-renders for some unrelated reason (say a different button was clicked).
numbersis still[10, 20, 30], so React skips the reduce and hands back the saved60— no adding up again. - Now
numberschanges to[10, 20, 30, 40]. The dependency changed, souseMemore-runs the calculation and stores the newtotal = 100.
Note: Output (the value you would see for total):
First render → 60
Unrelated re-render → 60 (re-used, not recalculated)
After numbers becomes [10, 20, 30, 40] → 100
The sum is only re-added when numbers actually changes — that is the saving.
Watch out: Do not optimise everything — these hooks add complexity. Reach for them only when you have a real, measured performance problem (expensive calculations, large lists, or passing callbacks to memoised children).
Tip: Beginner advice: write clear code first. Add useMemo/useCallback later, only where profiling shows they help. Premature optimisation hurts readability.
Q. What does useMemo do?
✍️ Practice
- Wrap an expensive calculation in
useMemowith the right dependencies. - Wrap a callback in
useCallback.
🏠 Homework
- Read about React performance and write down two situations where memoisation genuinely helps.