Programmatically measure render performance.
The Profiler Component
jsximport { Profiler } from 'react'; function App() { const onRenderCallback = ( id, // "id" prop of the Profiler phase, // "mount" | "update" | "nested-update" actualDuration, // Time spent rendering baseDuration, // Estimated time without memoization startTime, // When React started rendering commitTime, // When React committed changes ) => { console.log({ id, phase, actualDuration, baseDuration, }); }; return ( <Profiler id="App" onRender={onRenderCallback}> <MainContent /> </Profiler> ); }
Nested Profilers
jsxfunction App() { return ( <Profiler id="App" onRender={handleRender}> <Header /> <Profiler id="MainContent" onRender={handleRender}> <ProductList /> </Profiler> <Profiler id="Sidebar" onRender={handleRender}> <Sidebar /> </Profiler> </Profiler> ); }
Collecting Metrics
jsxconst metrics = []; function onRenderCallback(id, phase, actualDuration, baseDuration) { metrics.push({ id, phase, actualDuration, baseDuration, timestamp: Date.now(), }); // Warn on slow renders if (actualDuration > 16) { // More than 1 frame at 60fps console.warn(`Slow render: ${id} took ${actualDuration.toFixed(2)}ms`); } } // Send to analytics window.addEventListener('beforeunload', () => { if (metrics.length > 0) { navigator.sendBeacon('/api/metrics', JSON.stringify(metrics)); } });
Production Profiling
jsx// Create a profiling build // In package.json scripts: { "build:profile": "react-scripts build --profile" }
Or with Vite:
js// vite.config.js export default defineConfig({ build: { sourcemap: true, }, define: { 'process.env.ENABLE_PROFILING': 'true', }, });
Custom Performance Marks
jsxfunction ExpensiveOperation() { useEffect(() => { performance.mark('expensive-start'); // Do expensive work doExpensiveWork(); performance.mark('expensive-end'); performance.measure( 'expensive-operation', 'expensive-start', 'expensive-end' ); const measure = performance.getEntriesByName('expensive-operation')[0]; console.log(`Operation took ${measure.duration}ms`); }, []); }
React DevTools Profiler Settings
- Record why each component rendered
- Hide commits below threshold
- Show native elements
Access via: Components → Settings (gear icon)