Javascript 如何用HOC包装每个导出的组件?

Javascript 如何用HOC包装每个导出的组件?,javascript,reactjs,ecmascript-6,components,es6-modules,Javascript,Reactjs,Ecmascript 6,Components,Es6 Modules,我需要将添加[data test id]属性用于测试目的的可能性添加到我的React函数组件的中。为了实现这一点,我创建了withTestId()HOC,它将可选的proptestId添加到包装的组件中,当它被定义时,它将[data test id]添加到最终的HTML中 因此,当我定义组件时,如: 它返回: 我唯一的问题是将它应用于每个组件,而不必在每个组件中单独包装它。因此,不要像这样编写代码: 函数ExampleComponent(){…} 使用TestID导出默认值(示例组件)

我需要将添加
[data test id]
属性用于测试目的的可能性添加到我的React函数组件的中。为了实现这一点,我创建了
withTestId()
HOC,它将可选的prop
testId
添加到包装的组件中,当它被定义时,它将
[data test id]
添加到最终的HTML中

因此,当我定义组件时,如:


它返回:


我唯一的问题是将它应用于每个组件,而不必在每个组件中单独包装它。因此,不要像这样编写代码:

函数ExampleComponent(){…}
使用TestID导出默认值(示例组件)
我想将我所有的导出都打包到我的
index.ts
文件中,该文件现在看起来如下:

从“/ExampleComponent”导出{default as ExampleComponent};
从“/ExampleComponent2”导出{default as ExampleComponent2}”;
...

我怎样才能做到这一点呢?

我认为有两种方法可以做到这一点;一种动态方式,使库的用户代码更加复杂。您可以轻松地更改实现,而另一个实现需要更多的样板代码,从而保持用户代码不变

我还没有测试他们在捆绑代码时的树抖动行为

在用户代码中使用析构函数 这允许从主组件导出文件中添加/删除内容,而无需担心库中的其他样板文件。高阶组件可以轻松打开/关闭。一个警告:用户代码需要使用解构来检索组件

新的
index.ts
文件如下所示,而我在同一目录中调用了以前的
index.ts
文件
components.ts

import*作为“/components”中的常规组件;
从“/使用测试id”导入withTestId;
常量WithTestedComponents=对象
.钥匙(常规部件)
.reduce((testicomps,key)=>{
返回{
…测试组件,
[键]:带TestID(常规组件[键])
};
}, {});
导出带有TestedComponents的默认值;
要在应用程序代码中使用它,请执行以下操作:

import MyComponents from "./components/tested";
const { Component1, Component2, Component3, Component4 } = MyComponents;
这使用了
default
导出,使其看起来像是所有组件都在一个地方,但由于无法直接分解导出,因此需要执行第二步以从中获取正确的组件

将样板文件添加到导出文件 由于有一个包含库中导出的所有组件的
index.ts
文件,因此可以导入/重命名每个组件,并使用
withTestId
及其名称重新导出它们:

import withTestId from "./with-test-id";
import { default as TmpComponent1 } from "./component1";
import { default as TmpComponent2 } from "./component2";
import { default as TmpComponent3 } from "./component3";
import { default as TmpComponent4 } from "./component4";
export const Component1 = withTestId(TmpComponent1);
export const Component2 = withTestId(TmpComponent2);
export const Component3 = withTestId(TmpComponent3);
export const Component4 = withTestId(TmpComponent4);
这样,可以像以前一样使用导入:

import {
  Component1,
  Component2,
  Component3,
  Component4
} from "./components";
我认为使用
索引
文件已经是一种样板,这种方法增加了这种样板。因为用户代码不需要任何更改,所以我赞成这种方法

在我们的一个项目中,每当我们生成一个新组件时,我们都使用一个自定义脚本为我们创建这种样板文件

例子
这里有一个例子来说明这两种方法。

如果您想在任何地方都使用HoC,我不确定它是否是一种可行的方法。那么您还可以推荐什么呢?默认情况下,数据属性已经是有效的道具,为什么不只使用
并确保使用
将未知道具应用到每个组件的根元素?不再需要HoC,它可以处理您希望应用于组件的任何内容。尽管这取决于你对道具的管理程度。我个人经常使用它,但我也会在组件树的所有不同级别过滤掉任何不需要的道具。如果你有道具类型验证,当无意中传递额外道具时,你会收到警告或错误,因此可以安全地禁用
jsx道具no spreading
。它仍然会对可维护性产生一点影响,但会大大减少样板文件、树深度(每个HoC都会增加)、改善树抖动(其中导出所有内容的索引会大大削弱树抖动),总的来说,由于传播是一种常见的模式,与导出代码生成等相比,复杂性更低。我认为我将使用这种方法。你说得对,当我进行类型验证时,使用它是安全的。当然,这个规则有它的优点和缺点,但我开始认为禁用它比打开它有更多的积极方面。谢谢你的回复。我还认为,第二种办法是更好的选择。我将尝试编写一些脚本来为我生成这些
index.ts
文件,这听起来是最好的解决方案。当您使用
起飞
脚本时,您必须手动运行它,对吗?或者,当一个新组件到达时,您是否有一个运行脚本的观察者?我使用takeoff同时生成组件和导出。CLI可以调用脚本并生成多个文件或更改某些index.ts文件等。