@mouaad_idoufkir/why-render
v0.25.21
Published
A comprehensive React 19 developer tool that detects unnecessary re-renders with visual debugging panels, performance monitoring, and AI-powered suggestions.
Maintainers
Readme
@mouaad_idoufkir/why-render
A comprehensive, lightweight developer tool for React 19 that detects unnecessary re-renders, visualizes performance with a Flame Graph, and helps you optimize your application.
🚀 Why use this?
React is fast, but unnecessary re-renders can slow down your app. Identifying why a component re-rendered (was it a prop change? a state update? a parent render?) can be difficult.
@mouaad_idoufkir/why-render solves this by:
- Tracking every render and its cause.
- Diffing props to show exactly what changed (value vs. reference).
- Visualizing performance with an interactive Flame Graph and Timeline.
- Zero Overhead in production (fully tree-shakeable).
📦 Installation
npm install @mouaad_idoufkir/why-render
# or
yarn add @mouaad_idoufkir/why-render
# or
pnpm add @mouaad_idoufkir/why-render🏁 Quick Start
1. Add the DevTools (Optional but Recommended)
Add the <WhyRenderDevTools /> component to the root of your application (e.g., in App.tsx or main.tsx).
import React from 'react';
import { WhyRenderDevTools } from '@mouaad_idoufkir/why-render/ui';
const App = () => {
return (
<>
<MyComponent />
{/* Only renders in development */}
<WhyRenderDevTools />
</>
);
};2. Track a Component
Use the useWhyRender hook inside any component you want to debug.
import { useWhyRender } from '@mouaad_idoufkir/why-render';
const UserProfile = (props) => {
// 1. Pass props
// 2. Pass a unique name for the component
useWhyRender(props, 'UserProfile');
return <div>{props.name}</div>;
};Open your browser console or the WhyRender DevTools panel to see the logs!
🛠 Features & Usage
Hooks & HOCs
useWhyRender(props, componentName, options?)
The primary hook for functional components.
useWhyRender(props, 'MyComponent', {
verbose: true, // Log full diffs to console
compareStrategy: 'deep' // 'shallow' | 'deep' | 'fast-deep'
});withWhyRender(Component, options?)
A Higher-Order Component (HOC) for class components or when you prefer wrapping exports.
import { withWhyRender } from '@mouaad_idoufkir/why-render';
const MyComponent = (props) => <div>...</div>;
export default withWhyRender(MyComponent, { verbose: true });DevTools UI
The library comes with a powerful DevTools UI that overlays your application.
- Toggle: Click the floating "WR" badge or press
Ctrl+Shift+X. - Flame Graph: Visualize which components are taking the most time to render.
- Component Tree: See the hierarchy of tracked components.
- Timeline: View a chronological history of all render events.
- Diff Viewer: Inspect exactly which props changed between renders.
Diffing Strategies
You can configure how the library compares props to detect changes:
shallow(Default): UsesObject.is. Fast and standard for React.fast-deep: Recursive comparison with a depth limit (default 3). Good for checking if nested data changed structure.deep: Full deep equality check. Useful for finding "reference stability" issues (e.g., a new object with the same content is passed every time).custom: Provide your own comparison function.
useWhyRender(props, 'ComplexData', {
compareStrategy: 'deep'
});⚙️ Configuration Options
| Option | Type | Default | Description |
| :--- | :--- | :--- | :--- |
| compareStrategy | 'shallow' \| 'deep' \| 'fast-deep' | 'shallow' | How to compare props. |
| verbose | boolean | false | If true, logs detailed diffs to the console. |
| skipKeys | string[] | [] | List of prop names to ignore during comparison. |
| trackHooks | boolean | true | (Experimental) Attempt to track hook changes. |
🚀 Production Optimization
This library is designed to be Zero Overhead in production.
- Tree Shaking: The
package.jsonis marked with"sideEffects": false. - Dev-Only Guards: All logic is wrapped in
process.env.NODE_ENV !== 'production'checks. - Empty Exports: In production builds, hooks and HOCs are replaced with no-ops.
Ensure your bundler (Vite, Webpack, etc.) is configured to handle process.env.NODE_ENV.
🤝 Contributing
Contributions are welcome! Please read our Architecture Guide to understand the internals.
- Fork the repo.
- Install dependencies:
npm install - Run tests:
npm test - Submit a PR.
📄 License
MIT © Mouaad Idoufkir
