React Profiler & DevTools
You cannot optimize what you cannot measure. The React DevTools Profiler shows you exactly which components re-render, how long they take, and why — giving you precise, actionable performance data instead of guesses.
Reading the Flame Graph
- Install React DevTools browser extension — open DevTools → Profiler tab
- Click Record, interact with your app (clicks, typing, navigation), then stop recording
- Flame graph: each bar = one component. Width = render time. Gray = didn't render (memoized successfully). Color = render time (yellow/red = slow)
- Commit selector: each commit = one React update. Click through commits to see what caused each re-render
- 'Why did this render?' tooltip: React 18 DevTools shows the exact changed props, state, or context that caused a component to re-render
- Ranked chart view: sorts all components by render time — immediately shows your worst offender
- Golden rule: ALWAYS profile first, then optimize. Premature optimization wastes time and adds complexity for zero visible gain
Profiler API — Programmatic Measurement
import { Profiler, type ProfilerOnRenderCallback } from 'react';
// Profiler component — wraps any subtree, calls onRender after every render
const onRenderCallback: ProfilerOnRenderCallback = (
id, // the "id" prop of the Profiler tree
phase, // 'mount' or 'update'
actualDuration, // time spent rendering in ms
baseDuration, // estimated time without memoization
startTime,
commitTime
) => {
// Send to analytics
if (actualDuration > 16) { // > 16ms = missed a 60fps frame
console.warn(`[Perf] ${id} ${phase} took ${actualDuration.toFixed(2)}ms`);
analytics.track('slow_render', { component: id, duration: actualDuration, phase });
}
};
function App() {
return (
<Profiler id="ProductList" onRender={onRenderCallback}>
<ProductList />
</Profiler>
);
}
// Profiler is automatically removed in production builds
// baseDuration shows potential savings if you add memoization
// If actualDuration ≈ baseDuration, memoization wouldn't help
// If actualDuration << baseDuration, your memoization is workingCommon Mistakes — Profiling
- Profiling in development mode — dev mode is 2-3x slower due to extra checks; always profile in production mode (`npm run build && npm run preview`) for realistic numbers
- Optimizing without a baseline — measure before AND after; a 5ms render taking 2ms is 60% faster but completely imperceptible to users
- Confusing render count with render time — a component that renders 100 times in 1ms is fine; one that renders 3 times in 200ms is the real problem
Tip
Tip
Practice React Profiler DevTools in small, isolated examples before integrating into larger projects. Breaking concepts into small experiments builds genuine understanding faster than reading alone.
React.memo for components. useMemo for expensive computations. useCallback with memo'd children.
Practice Task
Note
Practice Task — (1) Write a working example of React Profiler DevTools from scratch without looking at notes. (2) Modify it to handle an edge case (empty input, null value, or error state). (3) Share your solution in the Priygop community for feedback.
Quick Quiz
Common Mistake
Warning
A common mistake with React Profiler DevTools is skipping edge case testing — empty inputs, null values, and unexpected data types. Always validate boundary conditions to write robust, production-ready react code.
Key Takeaways
- You cannot optimize what you cannot measure.
- Install React DevTools browser extension — open DevTools → Profiler tab
- Click Record, interact with your app (clicks, typing, navigation), then stop recording
- Flame graph: each bar = one component. Width = render time. Gray = didn't render (memoized successfully). Color = render time (yellow/red = slow)