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:

  1. Open React DevTools (F12 → React tab)
  2. Click “Profiler” tab
  3. Click record button (●)
  4. Interact with your app
  5. Click stop button (■)
  6. 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:

  1. Open Chrome DevTools (F12)
  2. Go to Performance tab
  3. Click record (●)
  4. Interact with your app
  5. Click stop (■)
  6. 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.

For performance optimization techniques, check out how to prevent unnecessary re-renders in React and how to fix memory leaks in React.


Speed up your responsive apps and websites with fully-featured, ready-to-use open-source admin panel templates—free to use and built for efficiency.


About the Author

Subscribe to our newsletter
Get early information about new products, product updates and blog posts.
What is JavaScript Array.pop() Method?
What is JavaScript Array.pop() Method?

The Wacky World of JavaScript: Unraveling the Oddities
The Wacky World of JavaScript: Unraveling the Oddities

How to convert a string to boolean in JavaScript
How to convert a string to boolean in JavaScript

How to limit items in a .map loop in JavaScript
How to limit items in a .map loop in JavaScript

Answers by CoreUI Core Team