我需要在我的React函数组件的ALL中添加为测试目的添加[data-test-id]
属性的可能性。为此,我创建了withTestId()
HOC,该HOC将可选的prop testId
添加到包装的组件中,并且在定义后将[data-test-id]
添加到最终HTML中。
所以当我定义类似的组件时:
<ExampleComponent testId="example" />
返回:
<div data-test-id="example" />
我唯一的问题是将其应用于每个组件,而不必将其分别包装在每个组件中。因此,而不是像这样编写代码:
function ExampleComponent() { ... }
export default withTestId(ExampleComponent)
我想将所有导出文件包装在index.ts
文件中,该文件现在看起来像这样:
export { default as ExampleComponent } from "./ExampleComponent";
export { default as ExampleComponent2 } from "./ExampleComponent2";
...
我该如何实现?
我看到了两种方法;一种动态方式,使您的库的用户代码更加复杂。这样您就可以轻松更改实现,而另一种则需要更多样板代码,并保持用户代码不变。
捆绑代码时,我还没有测试他们关于摇树的行为。
这允许您在主要组件导出文件中添加/删除内容,而不必担心库中的其他样板文件。高阶分量可以很容易地打开/关闭。一个警告:用户代码需要使用解构来检索组件。
您的新index.ts
文件看起来像这样,而我在同一目录中调用了您先前的index.ts
文件components.ts
:
import * as RegularComponents from "./components";
import withTestId from "./with-test-id";
const WithTestIdComponents = Object
.keys(RegularComponents)
.reduce((testIdComps, key) => {
return {
...testIdComps,
[key]: withTestId(RegularComponents[key])
};
}, {});
export default WithTestIdComponents;
要在您的应用程序代码中使用它:
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";
我认为使用index
文件已经是一种样板,并且这种方法增加了它。由于用户代码不需要任何更改,因此我倾向于这种方法。
在我们的一个项目中,无论何时生成新组件,我们都使用自定义takeoff脚本为我们创建这种样板。
这里是code sandbox,可以看到两种方法。