React DevTools Profiler
Use the React DevTools Profiler to find wasted renders: record, ranked chart, commit flamegraph, and what to fix first.
- react
- react-devtools
Guessing with memo is cargo cult. The React DevTools Profiler shows which components committed, how long they took, and why they rendered — evidence for performance work.
Docs: Profiler API, browser extension: React DevTools.
How to record
- Install React DevTools.
- Open Profiler tab.
- Click record, perform the slow interaction, stop.
- Inspect commits (each horizontal bar is a commit).
Look for:
- Long commits after a keystroke or click.
- Components that re-render with no prop/state change (yellow/gray cues depend on version — read the “why did this render” panel).
- Cascades from context or parents.
Flamegraph and ranked
- Flamegraph: width ≈ time; find heavy subtrees.
- Ranked: sorted list of expensive components in a commit.
- Timeline (when available): interaction-centric view.
// Optional: mark product interactions
import { Profiler } from 'react';
function onRender(id, phase, actualDuration) {
if (actualDuration > 16) {
console.debug(id, phase, actualDuration);
}
}
<Profiler id="SearchResults" onRender={onRender}>
<Results query={query} />
</Profiler>
Use sparingly in production; prefer DevTools while developing.
What to do with findings
| Finding | Action |
|---|---|
| Parent re-renders huge pure child | State colocation, composition, maybe memo |
| Context hammering a tree | Split context, move high-churn state |
| List mount cost | Virtualize, simplify row |
| Expensive pure calc | useMemo after proof |
| Effect loops | Fix deps (dependency array) |
Settings that help
Enable Record why each component rendered in Profiler settings. Disable browser extensions that inject noise when measuring.
Interview out-loud
“I profile with React DevTools before optimizing. I record the slow interaction, inspect commit flamegraphs for expensive subtrees, check why components rendered, then fix ownership or memoize based on evidence — not by wrapping everything in memo.”
Related on this site
Further reading
Edge cases worth rehearsing
Interviewers and production incidents cluster around the same edges: first render versus update, empty and loading states, Strict Mode double setup, concurrent interruptions, and what happens when identity (key, route params, user id) changes mid-edit. Walk one concrete user journey end-to-end — open, edit, navigate away, come back — and say which state survives.
Prefer fixing data flow and ownership before reaching for memoization or micro-optimizations. Prefer event handlers over effects when a user action is the trigger. Prefer deriving values during render over mirroring props into state. Prefer stable list keys from business ids. Measure with the profiler when performance is the claim.
When you cite an API, mention one failure mode: abort on unmount, serializable props across server/client boundaries, focus restoration for dialogs, or cache invalidation after a mutation. Specific beats generic every time.
Edge cases worth rehearsing
Interviewers and production incidents cluster around the same edges: first render versus update, empty and loading states, Strict Mode double setup, concurrent interruptions, and what happens when identity (key, route params, user id) changes mid-edit. Walk one concrete user journey end-to-end — open, edit, navigate away, come back — and say which state survives.
Prefer fixing data flow and ownership before reaching for memoization or micro-optimizations. Prefer event handlers over effects when a user action is the trigger. Prefer deriving values during render over mirroring props into state. Prefer stable list keys from business ids. Measure with the profiler when performance is the claim.
When you cite an API, mention one failure mode: abort on unmount, serializable props across server/client boundaries, focus restoration for dialogs, or cache invalidation after a mutation. Specific beats generic every time.
Related guides
- useCopyToClipboard HookCopy text with navigator.clipboard, fallback execCommand, transient copied state, and permissions that fail in insecure contexts.
- useDebouncedValue HookDebounce a changing value in React without firing effects on every keystroke. Cleanup, leading vs trailing, and the stale timer that updates unmounted state.
- useEventListener HookAttach a window, document, or element listener with a stable handler ref so you do not rebind on every render. Capture option and target changes.
- useFetch With AbortControllerFetch in an effect with a signal, ignore aborted errors, and prevent the slow response from winning a race after the url changes.
- useIdle HookDetect idle users: reset a timer on input events, fire idle after timeout, and decide whether mount starts the timer immediately.