Skip to content

pie6k/react-debug-updates

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

33 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

react-debug-updates

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.

highlight overlays zero config

demo

Why?

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.

How it works

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, or useContext hook triggered each re-render, with previous→next values

Install

npm install react-debug-updates
# or
yarn add react-debug-updates
# or
pnpm add react-debug-updates

Quick start

Import 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();

Dev-only guard

if (process.env.NODE_ENV === "development") {
  const { startReactUpdatesMonitor } = await import("react-debug-updates");
  startReactUpdatesMonitor();
}

With options

startReactUpdatesMonitor({
  reasonOfUpdate: true,
  logToConsole: true,
  highlightOpacity: 0.5,
  highlightShowLabels: false,
});

Requirements

  • A React dev build (which automatically creates __REACT_DEVTOOLS_GLOBAL_HOOK__) — no browser extension needed
  • For reasonOfUpdate and render durations: React must be in dev mode (provides _debugHookTypes and actualDuration on fibers)

API

startReactUpdatesMonitor(options?): () => void

Returns a stop function to unhook from React and remove all overlays. Throws if called in a non-browser environment (e.g. SSR).

Options

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)

UpdateCause

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

Console output

⚛ 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

Visual highlights

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)

License

MIT

About

See why React components re-render — visual overlays, console logging, and hook-level cause detection with zero code changes

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors