Monkey patches React to notify about avoidable re-renders by tracking pure components and hooks.
npx @tessl/cli install tessl/npm-welldone-software--why-did-you-render@10.0.0Why Did You Render is a React development tool that monkey patches React to detect and notify developers about potentially avoidable component re-renders. It tracks pure components (React.PureComponent and React.memo) and custom hooks, analyzing prop and state changes to identify when components re-render with identical values. Works with both React web applications and React Native.
npm install @welldone-software/why-did-you-render --save-devimport whyDidYouRender from '@welldone-software/why-did-you-render';For CommonJS:
const whyDidYouRender = require('@welldone-software/why-did-you-render');JSX Runtime (for React 19 automatic JSX transformation):
// These are handled automatically when configured as importSource
import '@welldone-software/why-did-you-render/jsx-runtime';
import '@welldone-software/why-did-you-render/jsx-dev-runtime';import React from 'react';
import whyDidYouRender from '@welldone-software/why-did-you-render';
// Initialize the library (typically in your app's entry point)
if (process.env.NODE_ENV === 'development') {
whyDidYouRender(React, {
trackAllPureComponents: true,
trackHooks: true,
logOwnerReasons: true
});
}
// Your existing React components will now be tracked
const MyComponent = React.memo(({ name, age }) => {
return <div>{name} is {age} years old</div>;
});
// The component will be automatically tracked for re-renders
export default MyComponent;React Native Usage:
import React from 'react';
import whyDidYouRender from '@welldone-software/why-did-you-render';
// For React Native, use __DEV__ instead of process.env.NODE_ENV
if (__DEV__) {
whyDidYouRender(React, {
trackAllPureComponents: true,
trackHooks: true,
logOwnerReasons: true
});
}For React 19 with automatic JSX transformation, configure Babel to use the library's JSX runtime:
// babel.config.js
['@babel/preset-react', {
runtime: 'automatic',
development: process.env.NODE_ENV === 'development',
importSource: '@welldone-software/why-did-you-render',
}]Why Did You Render is built around several key components:
whyDidYouRender function that patches React to enable trackingMain function to initialize Why Did You Render with React and configure tracking options.
function whyDidYouRender(
React: typeof React,
options?: WhyDidYouRenderOptions
): typeof React;Built-in component tracking and notification system with detailed re-render analysis.
interface UpdateInfo {
Component: React.Component;
displayName: string;
prevProps: any;
prevState: any;
nextProps: any;
nextState: any;
prevHookResult: any;
nextHookResult: any;
reason: ReasonForUpdate;
options: WhyDidYouRenderOptions;
hookName?: string;
}
type Notifier = (updateInfo: UpdateInfo) => void;Component Tracking and Notifications
Advanced hook tracking for monitoring React hooks like useState, useReducer, and custom hooks.
interface HookDifference {
pathString: string;
diffType: string;
prevValue: any;
nextValue: any;
}
type ExtraHookToTrack = [any, string];Enhanced JSX transformation for React 19 automatic JSX runtime with seamless WDYR integration.
/**
* Enhanced jsxDEV function that wraps React's jsx-dev-runtime
* Automatically applies WDYR tracking to components during JSX transformation
*/
declare const jsxDEV: typeof import('react/jsx-dev-runtime').jsxDEV;interface WhyDidYouRenderOptions {
include?: RegExp[];
exclude?: RegExp[];
trackAllPureComponents?: boolean;
trackHooks?: boolean;
logOwnerReasons?: boolean;
trackExtraHooks?: Array<ExtraHookToTrack>;
logOnDifferentValues?: boolean;
hotReloadBufferMs?: number;
onlyLogs?: boolean;
collapseGroups?: boolean;
titleColor?: string;
diffNameColor?: string;
diffPathColor?: string;
textBackgroundColor?: string;
notifier?: Notifier;
getAdditionalOwnerData?: (element: React.Element) => any;
}
interface ReasonForUpdate {
hookDifferences: HookDifference[];
propsDifferences: boolean;
stateDifferences: boolean;
ownerDifferences?: {
propsDifferences?: HookDifference[];
stateDifferences?: HookDifference[];
hookDifferences?: Array<{
hookName: string;
differences: HookDifference[];
}>;
};
}
type WhyDidYouRenderComponentMember = WhyDidYouRenderOptions | boolean;
interface WdyrStore {
React: typeof React;
options: WhyDidYouRenderOptions;
origCreateElement: typeof React.createElement;
origCreateFactory: typeof React.createFactory;
origCloneElement: typeof React.cloneElement;
componentsMap: WeakMap<any, any>;
ownerDataMap: WeakMap<any, any>;
hooksInfoForCurrentRender: WeakMap<any, any>;
ownerBeforeElementCreation: any;
}React Module Augmentation:
The library extends React component interfaces to support the whyDidYouRender property:
declare module 'react' {
interface FunctionComponent<P = {}> {
whyDidYouRender?: WhyDidYouRenderComponentMember;
}
interface VoidFunctionComponent<P = {}> {
whyDidYouRender?: WhyDidYouRenderComponentMember;
}
interface ExoticComponent<P = {}> {
whyDidYouRender?: WhyDidYouRenderComponentMember;
}
namespace Component {
const whyDidYouRender: WhyDidYouRenderComponentMember;
}
}