How to Use React Profiler for Performance Monitoring
Use the
Profiler component from React to wrap parts of your UI and provide an onRender callback that logs render timings. This helps you measure how often and how long components render, aiding performance optimization.Syntax
The Profiler component wraps React components you want to measure. It requires two props:
id: a unique string to identify the profiler instance.onRender: a callback function called after each render with timing details.
Inside Profiler, place the components you want to track.
jsx
import React, { Profiler } from 'react'; function onRenderCallback( id, // the id prop of the Profiler phase, // either "mount" or "update" actualDuration, // time spent rendering the committed update baseDuration, // estimated time to render the entire subtree without memoization startTime, // when React began rendering this update commitTime, // when React committed this update interactions // the Set of interactions belonging to this update ) { console.log(`Profiler [${id}] ${phase} phase: ${actualDuration}ms`); } function App() { return ( <Profiler id="MyComponent" onRender={onRenderCallback}> <MyComponent /> </Profiler> ); }
Example
This example shows a simple counter component wrapped in Profiler. The onRender callback logs how long each render takes, helping you see performance in the browser console.
jsx
import React, { useState, Profiler } from 'react'; function onRenderCallback(id, phase, actualDuration) { console.log(`Profiler [${id}] ${phase} phase: ${actualDuration.toFixed(2)}ms`); } function Counter() { const [count, setCount] = useState(0); return ( <div> <p>Count: {count}</p> <button onClick={() => setCount(count + 1)}>Increment</button> </div> ); } export default function App() { return ( <Profiler id="Counter" onRender={onRenderCallback}> <Counter /> </Profiler> ); }
Output
Profiler [Counter] mount phase: 1.23ms
Profiler [Counter] update phase: 0.45ms
Common Pitfalls
- Not providing a unique
idfor eachProfilerinstance can make logs confusing. - Ignoring the
phaseparameter can lead to mixing mount and update timings. - Using
Profileron very large trees without memoization can add overhead. - Forgetting to check the browser console where the timing logs appear.
jsx
/* Wrong: Missing unique id and ignoring phase */ <Profiler onRender={(...args) => console.log(args)}> <MyComponent /> </Profiler> /* Right: Unique id and clear onRender callback */ <Profiler id="MyComponent" onRender={(id, phase, actualDuration) => { console.log(`${id} rendered during ${phase} in ${actualDuration}ms`); }}> <MyComponent /> </Profiler>
Quick Reference
React Profiler Cheat Sheet:
| Prop | Description |
|---|---|
| id | Unique string to identify the Profiler instance |
| onRender | Callback function called after each render with timing info |
| phase | "mount" or "update" indicating render type |
| actualDuration | Time spent rendering the update in milliseconds |
| baseDuration | Estimated time to render subtree without memoization |
Key Takeaways
Wrap components with
Profiler and provide a unique id and onRender callback to measure render times.Use the
onRender callback to log or analyze render durations for performance insights.Check the browser console to see profiler logs after component renders.
Avoid wrapping very large component trees without memoization to reduce profiling overhead.
Distinguish between "mount" and "update" phases to understand initial and subsequent renders.