why-did-you-render 高级配置与定制化

why-did-you-render 高级配置与定制化

【免费下载链接】why-did-you-render why-did-you-render by Welldone Software monkey patches React to notify you about potentially avoidable re-renders. (Works with React Native as well.) 【免费下载链接】why-did-you-render 项目地址: https://gitcode.com/gh_mirrors/wh/why-did-you-render

本文详细介绍了 why-did-you-render 库的高级配置与定制化功能,包括 include/exclude 过滤规则配置、trackAllPureComponents 全局追踪、自定义 Hook 追踪与第三方库集成,以及通知器定制与样式主题配置。通过这些高级功能,开发者可以精准控制组件重渲染监控范围,优化 React 应用性能分析体验。

include/exclude 过滤规则配置

在大型React应用中,监控所有组件的重渲染可能会产生大量不必要的日志输出,影响开发体验。why-did-you-render提供了强大的include/exclude过滤机制,允许开发者精确控制需要监控的组件范围,实现针对性的性能优化分析。

过滤规则的工作原理

why-did-you-render的过滤系统基于组件displayName的正则表达式匹配,采用优先级明确的决策流程:

mermaid

配置语法详解

include和exclude选项都接受正则表达式数组,用于匹配组件的displayName:

import React from 'react';
import whyDidYouRender from '@welldone-software/why-did-you-render';

if (process.env.NODE_ENV === 'development') {
  whyDidYouRender(React, {
    // 包含规则:只监控匹配的组件
    include: [
      /^Header/,       // 匹配所有以Header开头的组件
      /Button$/,       // 匹配所有以Button结尾的组件  
      /.*Modal.*/,     // 匹配所有包含Modal的组件
      /^Connect/,      // 匹配Redux连接组件
    ],
    
    // 排除规则:优先级高于include
    exclude: [
      /^DevTools/,     // 排除开发工具组件
      /.*Test.*/,      // 排除测试组件
      /Spinner/,       // 排除加载指示器
    ],
    
    trackAllPureComponents: true,
  });
}

实际应用场景

场景1:专注业务组件监控
// 只监控业务核心组件,排除第三方库和工具组件
whyDidYouRender(React, {
  include: [
    /^Product/,        // 产品相关组件
    /^Cart/,           // 购物车组件
    /^Checkout/,       // 结账流程组件
    /^UserProfile/,    // 用户资料组件
  ],
  exclude: [
    /^React/,          // React内部组件
    /^Styled/,         // styled-components生成的组件
    /^Dev/,            // 开发工具组件
  ]
});
场景2:Redux连接组件优化
import React from 'react';
import ReactRedux from 'react-redux';

whyDidYouRender(React, {
  include: [/^Connect/],  // 专门监控Redux连接组件
  trackExtraHooks: [
    [ReactRedux, 'useSelector']
  ]
});
场景3:按功能模块划分监控
// 分模块监控,便于针对性优化
const moduleFilters = {
  // 用户模块
  userModule: {
    include: [/^User/, /^Profile/, /^Settings/],
    exclude: [/.*Button.*/]
  },
  
  // 商品模块  
  productModule: {
    include: [/^Product/, /^Catalog/, /^Detail/],
    exclude: [/.*Image.*/]
  },
  
  // 订单模块
  orderModule: {
    include: [/^Order/, /^Checkout/, /^Payment/],
    exclude: [/.*Modal.*/]
  }
};

// 动态切换监控模块
function enableWDYRForModule(moduleName) {
  const config = moduleFilters[moduleName];
  whyDidYouRender(React, {
    include: config.include,
    exclude: config.exclude,
    trackAllPureComponents: true
  });
}

优先级规则说明

why-did-you-render的过滤系统遵循明确的优先级规则:

  1. 最高优先级exclude规则 - 匹配即排除,无视其他设置
  2. 组件级设置whyDidYouRender = false - 单个组件禁用监控
  3. Hook特定设置trackHooks: false - 仅针对Hook变更的禁用
  4. 包含规则include规则 - 匹配即包含监控
  5. Pure组件全局设置trackAllPureComponents: true
  6. 组件显式启用whyDidYouRender = true

调试技巧与最佳实践

1. 确认displayName匹配
// 调试函数:查看组件displayName
function debugComponentNames(components) {
  components.forEach(Comp => {
    const displayName = Comp.displayName || Comp.name;
    console.log('Component:', displayName);
  });
}

// 在配置前验证正则匹配
const testPattern = /^Connect/;
const componentNames = ['ConnectFunction', 'ConnectComponent', 'UserProfile'];
componentNames.forEach(name => {
  console.log(`${name} matches:`, testPattern.test(name));
});
2. 分层配置策略
// 基础配置:监控所有Pure组件
const baseConfig = {
  trackAllPureComponents: true,
  logOwnerReasons: true
};

// 开发环境增强配置
const devConfig = {
  ...baseConfig,
  include: [/^App/, /^Page/, /^Layout/],
  exclude: [/^Dev/]
};

// 性能分析专用配置
const perfConfig = {
  ...baseConfig,
  include: [/^ProductList/, /^UserGrid/, /^DataTable/],
  logOnDifferentValues: true  // 即使值不同也记录
};

// 按需切换配置
function configureWDYR(configType) {
  const configs = {
    development: devConfig,
    performance: perfConfig,
    default: baseConfig
  };
  
  whyDidYouRender(React, configs[configType] || configs.default);
}
3. 正则表达式技巧
// 精确匹配示例
const preciseIncludes = [
  /^ExactComponentName$/,     // 精确匹配
  /^Prefix.*/,                // 前缀匹配
  /.*Suffix$/,                // 后缀匹配
  /.*Contains.*/,             // 包含匹配
  /^(Comp1|Comp2|Comp3)/,     // 多选一匹配
  /^[A-Z][a-zA-Z]*$/,         // 首字母大写的组件名
];

// 排除常见不需要监控的组件
const commonExcludes = [
  /^[a-z]/,                   // 排除小写开头的(通常是DOM元素)
  /^react-/,                  // 排除react-前缀的第三方组件
  /-test$/,                   // 排除测试组件
  /\./,                       // 排除包含点的(可能是HOC生成的)
];

常见问题排查

问题1:配置不生效

原因:displayName不匹配或优先级冲突 解决方案

// 添加调试输出
whyDidYouRender(React, {
  include: [/MyComponent/],
  notifier: (updateInfo) => {
    console.log('Tracking:', updateInfo.displayName);
    // 默认notifier逻辑
  }
});
问题2:误匹配或漏匹配

原因:正则表达式过于宽泛或严格 解决方案

// 使用更精确的正则
include: [
  /^MyComponent$/,        // 精确匹配而不是/MyComponent/
  /^UserProfile(?!Container)/, // 负向先行断言,排除UserProfileContainer
]
问题3:性能影响

原因:监控组件过多 解决方案

// 分阶段监控
const phasedMonitoring = {
  stage1: { include: [/^Critical/] },
  stage2: { include: [/^Important/] },
  stage3: { include: [/^Normal/] },
  
  enableStage(stage) {
    whyDidYouRender(React, this[stage]);
  }
};

通过合理配置include/exclude规则,开发者可以精准控制why-did-you-render的监控范围,避免不必要的性能开销,专注于真正需要优化的组件,大幅提升React应用性能优化的效率和效果。

trackAllPureComponents 全局追踪

在大型React应用中,手动为每个PureComponent或memo组件添加whyDidYouRender = true标记会变得非常繁琐。trackAllPureComponents选项正是为了解决这个问题而设计的全局追踪功能,它能够自动追踪所有使用React.PureComponentReact.memo创建的组件。

启用全局追踪

要启用全局追踪功能,只需在初始化why-did-you-render时将trackAllPureComponents设置为true

import React from 'react';

if (process.env.NODE_ENV === 'development') {
  const whyDidYouRender = require('@welldone-software/why-did-you-render');
  whyDidYouRender(React, {
    trackAllPureComponents: true,  // 启用全局追踪
  });
}

工作原理

当启用trackAllPureComponents后,库会通过以下逻辑判断是否应该追踪组件:

mermaid

具体的实现逻辑在shouldTrack.js中:

export default function shouldTrack(Component, {isHookChange}) {
  const displayName = getDisplayName(Component);
  
  // 排除逻辑优先
  if (shouldExclude(displayName)) {
    return false;
  }
  
  if (Component.whyDidYouRender === false) {
    return false;
  }
  
  // 全局追踪逻辑
  return !!(
    Component.whyDidYouRender || (
      wdyrStore.options.trackAllPureComponents && (
        (Component && Component.prototype instanceof wdyrStore.React.PureComponent) ||
        isMemoComponent(Component)
      )
    ) ||
    shouldInclude(displayName)
  );
}

追踪的组件类型

trackAllPureComponents会追踪以下两种类型的组件:

组件类型描述示例
React.PureComponent继承自PureComponent的类组件class MyComponent extends React.PureComponent
React.memo使用memo高阶组件包装的函数组件const MemoizedComponent = React.memo(MyComponent)

精细控制与排除机制

虽然全局追踪很方便,但在某些情况下可能需要排除特定的组件。why-did-you-render提供了多种排除机制:

1. 使用exclude选项

通过正则表达式排除特定名称的组件:

whyDidYouRender(React, {
  trackAllPureComponents: true,
  exclude: [/^Internal/, /^Private/],  // 排除以Internal或Private开头的组件
});
2. 显式设置whyDidYouRender = false

在组件级别显式禁用追踪:

class InternalComponent extends React.PureComponent {
  static whyDidYouRender = false;  // 显式禁用追踪
  render() {
    return <div>Internal Content</div>;
  }
}
3. 优先级规则

排除机制的优先级顺序如下:

mermaid

实际应用场景

场景1:大型组件库的性能监控
// 监控整个组件库中的所有Pure组件
whyDidYouRender(React, {
  trackAllPureComponents: true,
  exclude: [/^Tooltip/, /^Portal/],  // 排除工具提示和门户组件
});

// 组件库中的Pure组件会自动被追踪
export const Button = React.memo(({ children, onClick }) => (
  <button onClick={onClick} className="btn">
    {children}
  </button>
));

export const Card = React.memo(({ title, content }) => (
  <div className="card">
    <h3>{title}</h3>
    <p>{content}</p>
  </div>
));
场景2:选择性排除性能敏感组件
whyDidYouRender(React, {
  trackAllPureComponents: true,
});

// 性能敏感组件显式排除
class HighFrequencyRenderer extends React.PureComponent {
  static whyDidYouRender = false;  // 高频渲染组件,避免性能开销
  
  render() {
    return <CanvasRenderer {...this.props} />;
  }
}

性能考虑

虽然trackAllPureComponents非常方便,但在使用时需要注意:

  1. 开发环境专用:始终确保只在开发环境中启用
  2. 选择性排除:对于高频更新的组件,考虑显式排除以避免性能影响
  3. 内存使用:全局追踪会增加内存使用,特别是在大型应用中

测试验证

why-did-you-render提供了完整的测试用例来验证全局追踪功能:

// 测试PureComponent追踪
test('Pure component', () => {
  whyDidYouRender(React, {
    trackAllPureComponents: true,
  });
  const isShouldTrack = shouldTrack(PureComponent, {isHookChange: false});
  expect(isShouldTrack).toBe(true);
});

// 测试Memo组件追踪  
test('Memo component', () => {
  whyDidYouRender(React, {
    trackAllPureComponents: true,
  });
  const isShouldTrack = shouldTrack(MemoComponent, {isHookChange: false});
  expect(isShouldTrack).toBe(true);
});

通过合理使用trackAllPureComponents选项,开发者可以轻松实现对整个应用中所有Pure组件的性能监控,快速识别不必要的重渲染,从而优化React应用的性能表现。

自定义 Hook 追踪与第三方库集成

why-did-you-render 提供了强大的自定义 Hook 追踪能力,特别是对于第三方库中的 Hook 函数。通过 trackExtraHooks 配置选项,开发者可以监控任何自定义 Hook 的状态变化,这对于调试复杂的应用状态管理至关重要。

跟踪第三方库 Hook

React 生态系统中存在大量优秀的第三方状态管理库,如 React-Redux、React-Query、Formik 等。这些库通常提供自定义 Hook 来处理状态逻辑。why-did-you-render 允许你追踪这些 Hook 的调用和返回值变化。

React-Redux 集成示例
import React from 'react';
import * as ReactRedux from 'react-redux';

if (process.env.NODE_ENV === 'development') {
  const whyDidYouRender = require('@welldone-software/why-did-you-render');
  whyDidYouRender(React, {
    trackExtraHooks: [
      [ReactRedux, 'useSelector'],
      [ReactRedux, 'useDispatch']
    ]
  });
}

在这个配置中,我们同时追踪了 useSelectoruseDispatch Hook,这样可以全面监控 Redux 状态管理的性能表现。

自定义 Hook 追踪机制

why-did-you-render 通过猴子补丁(monkey-patching)技术来拦截和包装目标 Hook。其内部实现流程如下:

mermaid

高级配置选项

除了基本的 Hook 追踪,why-did-you-render 还提供了细粒度的配置选项:

whyDidYouRender(React, {
  trackExtraHooks: [
    // 基础用法
    [ReactRedux, 'useSelector'],
    
    // 高级配置:指定路径追踪
    [CustomLibrary, 'useComplexHook', { path: 'data.result' }],
    
    // 排除依赖项报告
    [AnotherLibrary, 'useOptimizedHook', { dependenciesPath: 'deps', dontReport: true }]
  ],
  logOnDifferentValues: true, // 即使值不同也记录
  hotReloadBufferMs: 1000     // 热重载缓冲时间
});

多库集成实践

在实际项目中,往往需要同时集成多个第三方库。以下是一个综合配置示例:

import React from 'react';
import * as ReactRedux from 'react-redux';
import * as ReactQuery from 'react-query';
import * as Formik from 'formik';

if (process.env.NODE_ENV === 'development') {
  const whyDidYouRender = require('@welldone-software/why-did-you-render');
  whyDidYouRender(React, {
    trackExtraHooks: [
      // Redux 状态管理
      [ReactRedux, 'useSelector'],
      [ReactRedux, 'useDispatch'],
      [ReactRedux, 'useStore'],
      
      // React Query 数据获取
      [ReactQuery, 'useQuery'],
      [ReactQuery, 'useMutation'],
      [ReactQuery, 'useInfiniteQuery'],
      
      // Formik 表单管理
      [Formik, 'useFormik'],
      [Formik, 'useField'],
      [Formik, 'useFormikContext']
    ],
    include: [/^Connect/, /^Form/], // 只追踪特定组件
    logOwnerReasons: true           // 记录组件所有者信息
  });
}

性能监控数据表

通过 why-did-you-render 收集的 Hook 性能数据可以整理为详细的监控报表:

Hook 名称调用次数平均耗时(ms)重复渲染次数优化建议
useSelector1522.345使用 reselect 优化
useQuery8915.712增加 staleTime
useFormik675.123拆分表单组件
useMutation348.98合并相关操作

调试技巧与最佳实践

  1. 分层配置策略:根据开发阶段配置不同的追踪级别

    const trackingConfig = {
      development: {
        trackExtraHooks: [
          [ReactRedux, 'useSelector'],
          [ReactQuery, 'useQuery']
        ],
        trackAllPureComponents: true
      },
      staging: {
        trackExtraHooks: [
          [ReactRedux, 'useSelector']
        ],
        trackAllPureComponents: false
      }
    };
    
  2. 选择性追踪:避免过度追踪导致的性能开销

    // 只追踪特定模式的组件
    include: [/^Connected/, /^Form/],
    
    // 排除已知性能良好的组件
    exclude: [/^Static/, /^Icon/]
    
  3. 自定义通知器:创建适合团队需求的输出格式

    const customNotifier = ({ Component, hookName, prevHookResult, nextHookResult, reason }) => {
      if (reason.hookDifferences) {
        console.groupCollapsed(`🔄 ${hookName} changed in ${Component.displayName}`);
        console.log('Previous:', prevHookResult);
        console.log('Next:', nextHookResult);
        console.log('Differences:', reason.hookDifferences);
        console.groupEnd();
      }
    };
    

常见问题解决方案

问题:Webpack 模块导出重写问题

// 解决方案:确保正确的模块引用方式
const ReactRedux = require('react-redux');
// 而不是
import { useSelector } from 'react-redux';

问题:Hook 追踪不生效

// 确保 wdyr.js 是项目的第一个导入
import './wdyr'; // 必须第一个导入
import React from 'react';
import ReactDOM from 'react-dom';

问题:生产环境意外启用

// 使用环境变量严格限制
if (process.env.NODE_ENV === 'development' && process.env.REACT_APP_WDYR_ENABLED) {
  // 启用 why-did-you-render
}

通过合理的自定义 Hook 追踪配置,开发者可以深入理解第三方库的内部运作机制,及时发现性能瓶颈,并优化应用的整体性能表现。why-did-you-render 在这一领域的强大功能使其成为现代 React 应用开发不可或缺的性能分析工具。

通知器定制与样式主题配置

why-did-you-render 提供了强大的通知器定制和样式主题配置功能,让开发者能够完全控制重新渲染警告的显示方式和外观。通过自定义通知器,您可以将警告信息发送到不同的输出目标,集成到现有的日志系统中,或者创建完全自定义的警告界面。

默认通知器的工作原理

why-did-you-render 的默认通知器使用浏览器的 console.groupconsole.logconsole.groupEnd API 来组织警告信息。通知器接收一个包含完整重新渲染信息的 updateInfo 对象:

{
  Component,        // 重新渲染的组件类
  displayName,      // 组件显示名称
  hookName,         // 钩子名称(如果适用)
  prevProps,        // 之前的 props
  prevState,        // 之前的 state
  prevHookResult,   // 之前的钩子结果
  nextProps,        // 新的 props
  nextState,        // 新的 state
  nextHookResult,   // 新的钩子结果
  reason            // 重新渲染的原因分析
}

自定义通知器实现

您可以通过传递自定义的 notifier 函数来完全控制警告的输出方式。以下是一个将警告发送到远程日志服务的示例:

import React from 'react';

if (process.env.NODE_ENV === 'development') {
  const whyDidYouRender = require('@welldone-software/why-did-you-render');
  
  const customNotifier = (updateInfo) => {
    const { Component, displayName, reason } = updateInfo;
    
    // 发送到远程日志服务
    fetch('/api/render-warnings', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        component: displayName,
        timestamp: new Date().toISOString(),
        reason: reason,
        severity: 'warning'
      })
    });
    
    // 同时在控制台显示
    console.warn(`组件 ${displayName} 发生了不必要的重新渲染`, reason);
  };

  whyDidYouRender(React, {
    trackAllPureComponents: true,
    notifier: customNotifier
  });
}

样式主题配置

why-did-you-render 提供了丰富的样式配置选项,让您可以自定义警告信息的外观:

whyDidYouRender(React, {
  trackAllPureComponents: true,
  titleColor: '#ff4757',           // 标题颜色
  diffNameColor: '#2ed573',        // 差异名称颜色
  diffPathColor: '#1e90ff',        // 差异路径颜色
  textBackgroundColor: '#f1f2f6',  // 文本背景颜色
  collapseGroups: true,            // 默认折叠分组
  onlyLogs: false                  // 仅使用 console.log
});

集成现有日志系统

如果您已经在使用像 Sentry、LogRocket 或其他日志服务,可以将 why-did-you-render 集成到现有系统中:

const sentryNotifier = (updateInfo) => {
  const { Component, displayName, reason } = updateInfo;
  
  // 发送到 Sentry
  Sentry.captureMessage('不必要的重新渲染检测', {
    level: 'warning',
    extra: {
      component: displayName,
      reason: JSON.stringify(reason),
      timestamp: new Date().toISOString()
    }
  });
  
  // 保持原有的控制台输出
  const defaultNotifier = require('./defaultNotifier').default;
  defaultNotifier(updateInfo);
};

whyDidYouRender(React, {
  notifier: sentryNotifier
});

条件性通知

您可以根据特定的条件来决定是否发送通知,例如只在特定环境下或针对特定组件:

const conditionalNotifier = (updateInfo) => {
  const { Component, displayName } = updateInfo;
  
  // 只在开发环境且不是特定组件时发送通知
  if (process.env.NODE_ENV === 'development' && 
      !displayName.includes('IgnoreThisComponent')) {
    
    const defaultNotifier = require('./defaultNotifier').default;
    defaultNotifier(updateInfo);
  }
};

自定义控制台输出格式

如果您想要完全控制控制台的输出格式,可以创建自定义的控制台输出:

const formattedNotifier = (updateInfo) => {
  const { Component, displayName, reason } = updateInfo;
  
  console.groupCollapsed(`%c🔄 ${displayName}`, 
    'color: #ff6b6b; font-weight: bold;');
  
  if (reason.propsDifferences) {
    console.log('%cProps 变化:', 'color: #1e90ff; font-weight: bold;');
    reason.propsDifferences.forEach(diff => {
      console.log(`  ${diff.pathString}:`, diff.prevValue, '→', diff.nextValue);
    });
  }
  
  if (reason.stateDifferences) {
    console.log('%cState 变化:', 'color: #2ed573; font-weight: bold;');
    reason.stateDifferences.forEach(diff => {
      console.log(`  ${diff.pathString}:`, diff.prevValue, '→', diff.nextValue);
    });
  }
  
  console.groupEnd();
};

性能监控集成

将重新渲染警告与性能监控工具集成:

const performanceNotifier = (updateInfo) => {
  const { Component, displayName } = updateInfo;
  
  // 记录性能指标
  performance.mark(`wdyr-${displayName}-start`);
  
  // 使用默认通知器
  const defaultNotifier = require('./defaultNotifier').default;
  defaultNotifier(updateInfo);
  
  performance.mark(`wdyr-${displayName}-end`);
  performance.measure(
    `wdyr-${displayName}-processing`,
    `wdyr-${displayName}-start`,
    `wdyr-${displayName}-end`
  );
};

通知器配置选项

以下表格总结了所有可用的通知器相关配置选项:

选项类型默认值描述
notifierFunctiondefaultNotifier自定义通知器函数
consoleLogFunctionconsole.log自定义日志函数
consoleGroupFunctionconsole.group自定义分组函数
consoleGroupEndFunctionconsole.groupEnd自定义分组结束函数
titleColorString'#058'标题文本颜色
diffNameColorString'blue'差异名称颜色
diffPathColorString'red'差异路径颜色
textBackgroundColorString'white'文本背景颜色
collapseGroupsBooleanfalse是否默认折叠分组
onlyLogsBooleanfalse是否仅使用 console.log

高级自定义示例

以下是一个完整的高级自定义示例,集成了多种功能:

import React from 'react';

if (process.env.NODE_ENV === 'development') {
  const whyDidYouRender = require('@welldone-software/why-did-you-render');
  
  const advancedNotifier = (updateInfo) => {
    const { Component, displayName, reason, prevProps, nextProps } = updateInfo;
    
    // 1. 发送到分析服务
    analytics.track('unnecessary-rerender', {
      component: displayName,
      propsChanged: !!reason.propsDifferences,
      stateChanged: !!reason.stateDifferences
    });
    
    // 2. 条件性过滤
    const isIgnoredComponent = displayName.includes('Chart') || 
                              displayName.includes('Map');
    if (isIgnoredComponent) return;
    
    // 3. 自定义控制台输出
    console.groupCollapsed(`%c⚠️ ${displayName}`, 
      'background: #fff3cd; color: #856404; padding: 2px 6px; border-radius: 3px;');
    
    if (reason.propsDifferences && reason.propsDifferences.length > 0) {
      console.log('%c🔍 Props 差异:', 'color: #007bff; font-weight: bold;');
      reason.propsDifferences.forEach(({ pathString, diffType, prevValue, nextValue }) => {
        console.log(`   ${pathString}:`, 
          `%c${JSON.stringify(prevValue)}`, 'color: #dc3545;',
          '→',
          `%c${JSON.stringify(nextValue)}`, 'color: #28a745;'
        );
      });
    }
    
    console.groupEnd();
  };
  
  whyDidYouRender(React, {
    trackAllPureComponents: true,
    notifier: advancedNotifier,
    titleColor: '#856404',
    diffNameColor: '#007bff',
    diffPathColor: '#6c757d',
    textBackgroundColor: '#fff3cd',
    collapseGroups: true
  });
}

通过灵活运用通知器定制和样式主题配置,您可以将 why-did-you-render 完美集成到您的开发工作流中,获得符合团队习惯和项目需求的重新渲染警告体验。

总结

why-did-you-render 提供了丰富的高级配置选项,使开发者能够根据项目需求定制化性能监控方案。通过合理的过滤规则配置、全局追踪设置、第三方库集成和通知器定制,可以显著提升 React 应用的性能优化效率。这些功能特别适用于大型复杂项目,帮助开发者快速定位和解决不必要的重渲染问题,从而提升应用的整体性能和用户体验。

【免费下载链接】why-did-you-render why-did-you-render by Welldone Software monkey patches React to notify you about potentially avoidable re-renders. (Works with React Native as well.) 【免费下载链接】why-did-you-render 项目地址: https://gitcode.com/gh_mirrors/wh/why-did-you-render

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值