See exactly which React components re-render, how often, how long they take, and why — all without modifying your components.
Created and used at Screen Studio.
I needed to debug React re-render performance in an Electron app, but I could never get the official React DevTools to work with Electron. The integration is fragile, poorly documented, and breaks between versions. I just needed to see which components were re-rendering.
So I wrote this — a plug-and-play one-liner that gives you visual highlight overlays and console logging for React re-renders. No browser extension, no Electron hacks, no configuration. Works in any React web environment — browsers, Electron, iframes.
Hooks into __REACT_DEVTOOLS_GLOBAL_HOOK__ to intercept every React commit. Detects re-rendered components using the exact same fiber tree diffing approach as the official React DevTools — following their original implementation of didFiberRender and parallel tree walking. No React DevTools extension required. No wrappers, no HOCs, no code changes — just call startReactUpdatesMonitor() and you get:
- Visual highlights — highlight boxes on re-rendered DOM nodes with a heat-map color scale (blue → red as render count increases)
- Console logging — grouped, color-coded re-render reports with component tree paths and render durations
- Update reasons — pinpoint which
useState,useReducer,useSyncExternalStore, oruseContexthook triggered each re-render, with previous→next values
npm install react-debug-updates
# or
yarn add react-debug-updates
# or
pnpm add react-debug-updatesImport and call startReactUpdatesMonitor before React renders anything — ideally at the very top of your entry point. This ensures the hook is in place before the first commit.
import { startReactUpdatesMonitor } from "react-debug-updates";
// One-liner — visual highlights out of the box
const stop = startReactUpdatesMonitor();
// Later, to clean up:
stop();if (process.env.NODE_ENV === "development") {
const { startReactUpdatesMonitor } = await import("react-debug-updates");
startReactUpdatesMonitor();
}startReactUpdatesMonitor({
reasonOfUpdate: true,
logToConsole: true,
highlightOpacity: 0.5,
highlightShowLabels: false,
});- A React dev build (which automatically creates
__REACT_DEVTOOLS_GLOBAL_HOOK__) — no browser extension needed - For
reasonOfUpdateand render durations: React must be in dev mode (provides_debugHookTypesandactualDurationon fibers)
Returns a stop function to unhook from React and remove all overlays. Throws if called in a non-browser environment (e.g. SSR).
| Option | Type | Default | Description |
|---|---|---|---|
mode |
"self-triggered" | "all" |
"self-triggered" |
"self-triggered" tracks only components whose own state changed. "all" includes children swept by parent updates |
reasonOfUpdate |
boolean |
false |
Detect and display why each component re-rendered |
logToConsole |
boolean |
false |
Log re-renders to the console |
highlight |
boolean |
true |
Enable visual highlight overlays |
highlightShowLabels |
boolean |
true |
Show text labels (name, count, duration, cause) above highlights |
highlightOpacity |
number |
0.8 |
Peak opacity of highlight overlays (0–1) |
highlightFlushInterval |
number |
250 |
Milliseconds between highlight flush cycles |
highlightAnimationDuration |
number |
1200 |
Highlight fade-out animation duration (ms) |
| Property | Type | Description |
|---|---|---|
kind |
"hook" | "props" | "class-state" | "unknown" |
Category of the cause |
hookIndex |
number? |
Source-order index of the hook (0-based) |
hookType |
string? |
e.g. "useState", "useReducer", "useContext" |
previousValue |
unknown? |
Previous hook state value |
nextValue |
unknown? |
New hook state value |
⚛ 3 re-renders
Counter App → Dashboard (0.42ms)
↳ useState[0]: 5 → 6
TodoList App → Dashboard (1.03ms)
↳ props changed (parent re-rendered)
Sidebar App (0.15ms)
↳ useContext changed
Re-rendered components get a highlight box that fades out. The color shifts from blue to red as the same node re-renders repeatedly within a flush window — making "hot" components visually obvious.
Each highlight label shows: ComponentName ×count duration (cause)
MIT
