debugjavascriptreactTip
React DevTools Profiler — finding expensive renders
Viewed 0 times
React 16.5+ for Profiler API
React DevToolsProfilerperformanceflamegraphrender timewhy did this rendermemoization
browser
Problem
The app feels slow but you don't know which component is causing it. console.log timing is inaccurate and doesn't show the React render tree. Guessing which components to memoize wastes time and adds noise.
Solution
Use the React DevTools Profiler to identify expensive renders:
// 1. Install React DevTools browser extension
// 2. Open DevTools → Profiler tab
// 3. Click Record → interact with the app → Stop Recording
// What to look for:
// - 'Commit' graph: each bar is a render cycle (height = time taken)
// - 'Flamegraph': shows all components rendered in a commit (gray = did not render)
// - 'Ranked': components sorted by render time
// - 'Why did this render?': shows props/state that changed
// In code: use the Profiler API for production metrics
import { Profiler } from 'react';
function onRenderCallback(id, phase, actualDuration, baseDuration, startTime, commitTime) {
// id: tree identifier
// phase: 'mount' | 'update'
// actualDuration: time for this commit
// baseDuration: estimated time without memoization
if (actualDuration > 16) {
console.warn(
}
}
<Profiler id="main-content" onRender={onRenderCallback}>
<MainContent />
</Profiler>
// 1. Install React DevTools browser extension
// 2. Open DevTools → Profiler tab
// 3. Click Record → interact with the app → Stop Recording
// What to look for:
// - 'Commit' graph: each bar is a render cycle (height = time taken)
// - 'Flamegraph': shows all components rendered in a commit (gray = did not render)
// - 'Ranked': components sorted by render time
// - 'Why did this render?': shows props/state that changed
// In code: use the Profiler API for production metrics
import { Profiler } from 'react';
function onRenderCallback(id, phase, actualDuration, baseDuration, startTime, commitTime) {
// id: tree identifier
// phase: 'mount' | 'update'
// actualDuration: time for this commit
// baseDuration: estimated time without memoization
if (actualDuration > 16) {
console.warn(
Slow render in ${id}: ${actualDuration}ms);}
}
<Profiler id="main-content" onRender={onRenderCallback}>
<MainContent />
</Profiler>
Why
The Profiler captures accurate timing from React's internal commit phase. baseDuration shows how long rendering would take without any memoization — comparing this to actualDuration reveals how effective existing memoization is. 'Why did this render' shows exactly which prop or state changed.
Gotchas
- React DevTools Profiler is only available in development builds — production builds are optimized and don't expose profiling data
- Enable 'Record why each component rendered' in Profiler settings for the 'Why did this render?' panel
- React.Profiler API works in production — useful for tracking slow renders in the field
- Profiling adds overhead — remove Profiler wrappers before shipping to production
Code Snippets
Production performance tracking with Profiler
// Production profiling
import { Profiler } from 'react';
<Profiler
id="ProductList"
onRender={(id, phase, duration) => {
analytics.track('slow_render', { id, phase, duration });
}}
>
<ProductList />
</Profiler>Context
When the React app has perceived performance issues and you need to identify which components are slow to render
Revisions (0)
No revisions yet.