How to profile React rendering
React Profiler measures component render times and identifies performance bottlenecks in your application. As the creator of CoreUI with 12 years of React development experience, I’ve used React Profiler to optimize applications serving millions of users, reducing render times by up to 80% by identifying and eliminating unnecessary re-renders.
The most effective approach combines React DevTools Profiler with the Profiler API for production monitoring.
React DevTools Profiler
Install React DevTools browser extension, then:
- Open React DevTools (F12 → React tab)
- Click “Profiler” tab
- Click record button (●)
- Interact with your app
- Click stop button (■)
- Analyze flame graph
The flame graph shows:
- Width: Time spent rendering
- Color: Components that rendered (gray = didn’t render)
- Height: Component tree depth
Profiler API
import { Profiler } from 'react'
function onRenderCallback(
id, // Component name
phase, // "mount" or "update"
actualDuration, // Time spent rendering
baseDuration, // Estimated time without memoization
startTime, // When render started
commitTime, // When committed
interactions // Set of interactions
) {
console.log(`${id} (${phase}) took ${actualDuration}ms`)
}
function App() {
return (
<Profiler id="App" onRender={onRenderCallback}>
<Dashboard />
</Profiler>
)
}
Profile Specific Components
function Dashboard() {
return (
<div>
<Profiler id="Header" onRender={onRenderCallback}>
<Header />
</Profiler>
<Profiler id="Sidebar" onRender={onRenderCallback}>
<Sidebar />
</Profiler>
<Profiler id="Content" onRender={onRenderCallback}>
<Content />
</Profiler>
</div>
)
}
Send Profiling Data to Analytics
import { Profiler } from 'react'
function onRenderCallback(id, phase, actualDuration) {
// Only log slow renders
if (actualDuration > 100) {
// Send to analytics service
fetch('/api/metrics', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
component: id,
phase,
duration: actualDuration,
timestamp: Date.now()
})
})
}
}
Measure Re-renders
Track how many times components render:
import { useRef } from 'react'
function useRenderCount() {
const renderCount = useRef(0)
renderCount.current++
console.log(`Render #${renderCount.current}`)
return renderCount.current
}
function MyComponent({ data }) {
const renderCount = useRenderCount()
return (
<div>
<p>Rendered {renderCount} times</p>
<p>{data}</p>
</div>
)
}
Why Did You Render Library
Install:
npm install @welldone-software/why-did-you-render
Setup:
// wdyr.js
import React from 'react'
if (process.env.NODE_ENV === 'development') {
const whyDidYouRender = require('@welldone-software/why-did-you-render')
whyDidYouRender(React, {
trackAllPureComponents: true
})
}
Import in index.js:
import './wdyr' // Must be before React import
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(<App />)
Mark components to track:
function MyComponent(props) {
return <div>{props.value}</div>
}
MyComponent.whyDidYouRender = true
Performance Metrics
import { useEffect, useRef } from 'react'
function usePerformance(componentName) {
const renderStartTime = useRef(performance.now())
useEffect(() => {
const renderDuration = performance.now() - renderStartTime.current
console.log(`${componentName} render took ${renderDuration.toFixed(2)}ms`)
renderStartTime.current = performance.now()
})
}
function ExpensiveComponent() {
usePerformance('ExpensiveComponent')
// Component logic
return <div>Content</div>
}
Chrome Performance Tab
Record performance:
- Open Chrome DevTools (F12)
- Go to Performance tab
- Click record (●)
- Interact with your app
- Click stop (■)
- Look for:
- Long tasks (yellow bars)
- User interactions
- React render times
React.memo Profiling
Compare before and after memoization:
// Before
function UserCard({ user }) {
console.log('UserCard rendered')
return <div>{user.name}</div>
}
// After
const UserCard = React.memo(function UserCard({ user }) {
console.log('UserCard rendered')
return <div>{user.name}</div>
})
// Profile both versions
function App() {
const [count, setCount] = useState(0)
return (
<Profiler id="App" onRender={onRenderCallback}>
<button onClick={() => setCount(count + 1)}>
Count: {count}
</button>
<UserCard user={{ name: 'John' }} />
</Profiler>
)
}
Best Practice Note
This is the profiling workflow we use across all CoreUI React projects to identify performance bottlenecks. React DevTools Profiler shows which components render and how long they take, helping pinpoint unnecessary re-renders. Always profile in production mode with realistic data volumes, focus on components that render frequently or take >16ms, and use React.memo, useMemo, and useCallback strategically based on profiling results.
For production applications, consider using CoreUI’s React Admin Template which includes performance monitoring and optimized component patterns.
Related Articles
For performance optimization techniques, check out how to prevent unnecessary re-renders in React and how to fix memory leaks in React.



