React Profiler
Measure rendering performance of your components
📊 What is the Profiler?
The Profiler measures how often components render and the cost of rendering. It helps identify performance bottlenecks by tracking render times, allowing you to optimize slow components and improve app performance.
<Profiler id="App" onRender={callback}>
<App />
</Profiler>
Key Concepts
Render Time
Measure component render duration
Performance
Identify slow components
Metrics
Track rendering statistics
Optimization
Find areas to improve
🔹 Basic Profiler Usage
Wrap components with Profiler to measure their performance. The onRender callback receives detailed metrics about each render, including timing information and what caused the update.
import { Profiler } from 'react';
function onRenderCallback(
id, // Profiler id
phase, // "mount" or "update"
actualDuration, // Time spent rendering
baseDuration, // Estimated time without memoization
startTime, // When render started
commitTime, // When React committed
interactions // Set of interactions
) {
console.log(`${id} took ${actualDuration}ms to render`);
}
function App() {
return (
<Profiler id="App" onRender={onRenderCallback}>
<Dashboard />
</Profiler>
);
}
Console Output:
App took 12.5ms to render
🔹 Multiple Profilers
Use multiple Profilers to measure different parts of your app independently. This helps pinpoint exactly which sections are slow and need optimization.
import { Profiler } from 'react';
function App() {
return (
<div>
{/* Profile header separately */}
<Profiler id="Header" onRender={onRenderCallback}>
<Header />
</Profiler>
{/* Profile sidebar separately */}
<Profiler id="Sidebar" onRender={onRenderCallback}>
<Sidebar />
</Profiler>
{/* Profile main content separately */}
<Profiler id="Content" onRender={onRenderCallback}>
<MainContent />
</Profiler>
</div>
);
}
Console Output:
Header took 3.2ms to render
Sidebar took 8.7ms to render
Content took 15.3ms to render
🔹 Tracking Render Phases
Distinguish between mount and update phases to understand component behavior:
import { Profiler } from 'react';
function onRenderCallback(id, phase, actualDuration) {
if (phase === 'mount') {
console.log(`${id} mounted in ${actualDuration}ms`);
} else {
console.log(`${id} updated in ${actualDuration}ms`);
}
}
function UserProfile() {
return (
<Profiler id="UserProfile" onRender={onRenderCallback}>
<div>
<h2>User Profile</h2>
<UserDetails />
</div>
</Profiler>
);
}
Console Output:
UserProfile mounted in 10.2ms
UserProfile updated in 3.5ms
🔹 Performance Logging
Create a utility to log and analyze performance data:
import { Profiler } from 'react';
// Performance logger utility
const performanceLogger = (id, phase, actualDuration) => {
// Only log in development
if (process.env.NODE_ENV === 'development') {
const color = actualDuration > 10 ? '🔴' : '🟢';
console.log(
`${color} ${id} (${phase}): ${actualDuration.toFixed(2)}ms`
);
}
};
function App() {
return (
<Profiler id="App" onRender={performanceLogger}>
<ExpensiveComponent />
</Profiler>
);
}
🔹 Nested Profilers
Nest Profilers to measure component hierarchies and understand parent-child rendering relationships:
import { Profiler } from 'react';
function App() {
return (
<Profiler id="App" onRender={onRenderCallback}>
<div>
<h1>Dashboard</h1>
{/* Nested profiler for specific component */}
<Profiler id="DataTable" onRender={onRenderCallback}>
<DataTable />
</Profiler>
</div>
</Profiler>
);
}
🔹 Real-World Example
Complete example with performance tracking:
import { Profiler, useState } from 'react';
function App() {
const [count, setCount] = useState(0);
const handleRender = (id, phase, actualDuration) => {
console.log({
component: id,
phase: phase,
renderTime: `${actualDuration.toFixed(2)}ms`,
timestamp: new Date().toISOString()
});
};
return (
<Profiler id="Counter" onRender={handleRender}>
<div>
<h1>Count: {count}</h1>
<button onClick={() => setCount(count + 1)}>
Increment
</button>
</div>
</Profiler>
);
}
🔹 Best Practices
✅ Do:
- Use in development to find bottlenecks
- Profile specific slow components
- Compare before/after optimization
- Remove Profilers in production
❌ Don't:
- Leave Profilers in production code
- Profile every single component
- Ignore the performance data
- Optimize without measuring first