【问题标题】:How can I count the number of components on a page that have been connected with redux' connect() function?如何计算页面上已使用 redux 的 connect() 函数连接的组件数量?
【发布时间】:2019-02-19 15:52:33
【问题描述】:

我正在对使用许多连接组件(数百个)的大型 React/Redux 应用程序进行一些性能分析。

我想跟踪连接组件的数量作为性能指标,以便我可以准确估计每帧预算,例如mapStateToProps 和其他 Redux 逻辑。

React devtools 可以访问页面上的所有组件,因此我希望重用它所做的相同钩子,或者也接受任何允许我枚举页面上所有组件的钩子(从那里我可以判断它们是否包含在 Connect 中)。

【问题讨论】:

  • 一个潜在的潜在客户:github.com/bruderstein/react-render-hook
  • 这在 React devtool hooks 中绝对是可能的,但问题是 Redux 连接的组件不能明确地识别自己,并且Connect 组件类没有暴露给instanceof Connect 检查。 react-render-hook 没有监视连接组件的功能。

标签: reactjs react-redux


【解决方案1】:

react-redux 似乎没有挂钩连接组件的特定功能,而 Redux 开发工具作为中间件应用于存储,并且与连接的 React 组件无关。

一个简单的方法是猴子补丁react-redux 模块并扩展具有特定行为的连接组件,demo

import * as reactRedux from "react-redux";

let connectedCount = 0;

function patchConnect(connect) {
  return (...args) => {
    const wrapWithConnect = connect(...args);
    return WrappedComponent => {
      const Connect = wrapWithConnect(WrappedComponent);

      return class ConnectWithCounter extends Connect {
        componentDidMount() {
          console.log(++connectedCount, this);
          super.componentDidMount();
        }

        componentWillUnmount() {
          console.log(--connectedCount);
          super.componentWillUnmount();
        }
      };
    };
  };
}

reactRedux.connect = patchConnect(reactRedux.connect);
reactRedux.connectAdvanced = patchConnect(reactRedux.connectAdvanced);

// import the rest of the app that imports redux-react
import('./app').catch(console.error);

react-redux 应该先打补丁,模块应该是可写的。这对模块化环境施加了限制,因为 ES 模块可以是只读的(根据规范,它们是只读的)并且 import 语句可能在其余代码之前(它们应该根据规范)。 reactRedux.connect = ... 修补有可能发生得太晚或根本不会发生。

例如,该示例使用 Codesandbox,它会毫无错误地提升 import './app',而相同的示例在 Stackblitz 中不起作用,因为 SystemJS 模块实现会导致只读导入。

最好将开发环境配置为使用 CommonJS 模块,因为require 允许这种修改。

【讨论】:

  • 我相信我可以完成这项工作,但我目前陷入困境;无论我使用 import 还是 require ,我仍然会收到此错误:Uncaught TypeError: Cannot set property connect of #<Object> which has only a getter when setting reactRedux.connect;我现在正在查看 webpack/babel 文档以了解如何允许它
  • 是的,这就是答案所指的。尝试使用babeljs.io/docs/en/next/babel-preset-env.html#modules 禁用 Babel 中的模块转译并让 Webpack 处理它们,或者让 Babel 将模块转译为 CommonJS。另请参阅此主题,github.com/webpack/webpack/issues/4039
  • 遗憾地添加 @babel/plugin-transform-modules-commonjs 不起作用(同样的错误);我还在调查中
  • 此后尝试 rewiremock 和 inject-loader 均未成功
  • 这应该在转译器级别处理。像 inject-loader 这样的东西会做同样的事情,如答案所示。如果模块实现不允许这样做,它们将无法工作。我建议在单独的问题中解决这个问题,这对您的设置非常具体,stackoverflow.com/help/mcve 中的主脚本可以简化为import * as reactRedux from "react-redux"; reactRedux.connect = () => {}。我现在不怎么使用 Babel,所以我不确定我是否可以有效地帮助解决这部分问题。
猜你喜欢
  • 2012-07-20
  • 2019-11-22
  • 2016-03-17
  • 2021-02-24
  • 1970-01-01
  • 2023-03-22
  • 2021-12-27
  • 2018-04-05
  • 2020-10-02
相关资源
最近更新 更多