Monkey patches React to notify about avoidable re-renders by tracking pure components and hooks.
—
Core functionality for initializing Why Did You Render with React and configuring tracking options.
Initializes Why Did You Render by monkey patching React with re-render tracking capabilities.
/**
* Initialize Why Did You Render with React instance and configuration options
* @param React - The React instance to patch
* @param options - Configuration options for tracking behavior
* @returns The patched React instance with additional WDYR properties
*/
function whyDidYouRender(
React: typeof React,
options?: WhyDidYouRenderOptions
): typeof React;Usage Examples:
import React from 'react';
import whyDidYouRender from '@welldone-software/why-did-you-render';
// Basic initialization
whyDidYouRender(React);
// With configuration options
whyDidYouRender(React, {
trackAllPureComponents: true,
trackHooks: true,
logOwnerReasons: true,
include: [/^MyComponent/],
exclude: [/^ThirdParty/]
});TypeScript Setup:
For TypeScript projects, add the type reference directive at the top of your setup file:
/// <reference types="@welldone-software/why-did-you-render" />
import React from 'react';
import whyDidYouRender from '@welldone-software/why-did-you-render';
if (process.env.NODE_ENV === 'development') {
whyDidYouRender(React, {
trackAllPureComponents: true
});
}React Native Setup:
For React Native applications, setup varies depending on your workflow:
// React Native Bare Workflow
// babel.config.js
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
env: {
development: {
plugins: [['@babel/plugin-transform-react-jsx', {
runtime: 'automatic',
development: process.env.NODE_ENV === 'development',
importSource: '@welldone-software/why-did-you-render',
}]],
},
},
};
// wdyr.js setup file
import React from 'react';
if (__DEV__) {
const whyDidYouRender = require('@welldone-software/why-did-you-render');
whyDidYouRender(React, {
trackAllPureComponents: true,
trackHooks: true
});
}// Expo Managed Workflow
// babel.config.js
module.exports = function (api) {
api.cache(true);
return {
presets: [
[
"babel-preset-expo",
{
jsxImportSource: "@welldone-software/why-did-you-render",
},
],
],
};
};The main function includes several static properties for advanced usage:
/**
* Default notification handler for re-render events
* @param updateInfo - Information about the component update
*/
whyDidYouRender.defaultNotifier: (updateInfo: UpdateInfo) => void;
/**
* Internal store containing React instance, options, and tracking data
*/
whyDidYouRender.wdyrStore: WdyrStore;
/**
* Stores owner component data for render tracking
* @param element - React element to store owner data for
*/
whyDidYouRender.storeOwnerData: (element: React.Element) => void;
/**
* Gets the WDYR-patched version of a component type
* @param origType - Original component type
* @returns Patched component type or null if not trackable
*/
whyDidYouRender.getWDYRType: (origType: React.ComponentType) => React.ComponentType | null;
/**
* Gets the current owner component during rendering
* @returns Current owner component or null
*/
whyDidYouRender.getCurrentOwner: () => React.Component | null;
/**
* Creates a default notifier with hot reload handling
* @param hotReloadBufferMs - Buffer time in milliseconds to ignore updates after hot reload
* @returns Default notifier function with hot reload support
*/
whyDidYouRender.createDefaultNotifier: (hotReloadBufferMs?: number) => Notifier;Comprehensive configuration interface for controlling tracking behavior:
interface WhyDidYouRenderOptions {
/** Array of RegExp patterns to include - only components matching these patterns will be tracked */
include?: RegExp[];
/** Array of RegExp patterns to exclude - components matching these patterns will not be tracked */
exclude?: RegExp[];
/** Whether to automatically track all React.PureComponent and React.memo components */
trackAllPureComponents?: boolean;
/** Whether to track React hooks for state changes */
trackHooks?: boolean;
/** Whether to log information about the component that caused the re-render */
logOwnerReasons?: boolean;
/** Additional hooks to track beyond the built-in ones */
trackExtraHooks?: Array<ExtraHookToTrack>;
/** Whether to log even when values are different (normally only logs when values are the same) */
logOnDifferentValues?: boolean;
/** Buffer time in milliseconds to prevent logging during hot reload */
hotReloadBufferMs?: number;
/** Use console.log instead of console.group for simpler output */
onlyLogs?: boolean;
/** Use console.groupCollapsed instead of console.group for collapsed output */
collapseGroups?: boolean;
/** Color for component names in console output */
titleColor?: string;
/** Color for diff property names in console output */
diffNameColor?: string;
/** Color for diff property paths in console output */
diffPathColor?: string;
/** Background color for console text */
textBackgroundColor?: string;
/** Custom notification handler to replace the default console logger */
notifier?: Notifier;
/** Custom name to use in notifications */
customName?: string;
/** Function to extract additional data from React elements for owner tracking */
getAdditionalOwnerData?: (element: React.Element) => any;
}Components can be individually configured for tracking using the whyDidYouRender property:
type WhyDidYouRenderComponentMember = WhyDidYouRenderOptions | boolean;Usage Examples:
// Enable tracking for a specific component
const MyComponent = React.memo(({ data }) => {
return <div>{data.name}</div>;
});
MyComponent.whyDidYouRender = true;
// Configure tracking options for a specific component
const AnotherComponent = React.memo(({ items }) => {
return <ul>{items.map(item => <li key={item.id}>{item.name}</li>)}</ul>;
});
AnotherComponent.whyDidYouRender = {
logOnDifferentValues: true,
customName: 'ItemList'
};The library provides a way to remove its patches and restore React to its original state:
/**
* Reverts all Why Did You Render patches and restores React to original state
* This function is added to React after initialization
*/
React.__REVERT_WHY_DID_YOU_RENDER__(): void;Usage Example:
// Initialize WDYR
whyDidYouRender(React, options);
// Later, revert all changes
React.__REVERT_WHY_DID_YOU_RENDER__();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;
}Install with Tessl CLI
npx tessl i tessl/npm-welldone-software--why-did-you-render