The React Profiler is a tool built into the React Developer Tools extension that helps you measure and visualize component render performance.
It tracks which components render, how long they take, and what triggered those renders — making it invaluable for optimizing performance.
To access the Profiler:
You can now record and analyze rendering behavior in real time.
You can profile performance either via the browser DevTools or programmatically using the <Profiler> component.
// Example: Using the Profiler API
import React, { Profiler } from "react";
import AppContent from "./AppContent";
function App() {
const onRenderCallback = (id, phase, actualDuration) => {
// Log render metrics to the console
console.log(`${id} rendered in ${actualDuration.toFixed(2)}ms during ${phase}`);
};
return (
// Wrap the part of the app you want to measure
<Profiler id="AppContent" onRender={onRenderCallback}>
<AppContent />
</Profiler>
);
}
export default App;
AppContent rendered in 2.45ms during mount
The callback receives details like:
id – the component name being measuredphase – “mount” or “update”actualDuration – how long rendering took (in ms)baseDuration – estimated render cost without memoizationstartTime / commitTime – render timestampsThe visual Profiler provides an intuitive interface to analyze component performance.
Profiler displays:
Components that took longer to render appear in warmer colors (yellow/orange/red).
| Metric | Description |
|---|---|
actualDuration |
Time React spent rendering the component |
baseDuration |
Estimated cost if React rendered everything without memoization |
startTime / commitTime |
When render began and finished |
interactions |
Events (like clicks or inputs) that triggered this render |
// A simple app where Child renders too often
function Child({ onClick }) {
console.log("Child rendered");
return <button onClick={onClick}>Click</button>;
}
const MemoChild = React.memo(Child);
function Parent() {
const [count, setCount] = React.useState(0);
// ❌ This causes new function creation each render
const handleClick = () => setCount(count + 1);
return (
<div>
<p>Count: {count}</p>
// MemoChild re-renders because handleClick is a new reference
<MemoChild onClick={handleClick} />
</div>
);
}
In the Profiler, you’ll see Child re-rendering every time. The fix: wrap handleClick in useCallback() to stabilize its reference.
Below is a simulation of how the Profiler measures render costs. We are rendering 2,000 items. Without optimization, every item re-renders (expensive). With optimization, we skip unnecessary work.
React.memo() or useCallback() where needed.Goal: Learn to measure, analyze, and interpret render performance to make data-driven optimizations in React.