CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-welldone-software--why-did-you-render

Monkey patches React to notify about avoidable re-renders by tracking pure components and hooks.

Pending
Overview
Eval results
Files

core-setup.mddocs/

Core Setup and Configuration

Core functionality for initializing Why Did You Render with React and configuring tracking options.

Capabilities

Main Library Function

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",
        },
      ],
    ],
  };
};

Static Properties

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;

Configuration Options

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;
}

Component Integration

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'
};

Library Reversion

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

Internal Types

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@10.0.1

docs

component-tracking.md

core-setup.md

hook-tracking.md

index.md

tile.json