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

时间:2020-02-21 15:18:07

标签: javascript reactjs ecmascript-6 components es6-modules

我需要在我的React函数组件的 ALL 中添加添加[data-test-id]属性以进行测试的可能性。为此,我创建了withTestId() HOC,它向包装的组件中添加了可选的道具testId,并在其定义后向最终HTML中添加了[data-test-id]

所以当我定义类似这样的组件时:

<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";
...

我该如何实现?

1 个答案:

答案 0 :(得分:3)

我看到这样做的两种方式;一种动态的方式,使您的库的用户代码更加复杂。这样您就可以轻松更改实现,而另一种则需要更多样板代码,而无需更改用户代码。

在捆绑代码时,我还没有测试他们在摇树上的行为。

在用户代码中使用销毁

这允许您在主要组件导出文件中添加/删除内容,而不必担心库中的其他样板文件。高阶分量可以很容易地打开/关闭。一个警告:用户代码需要使用解构来检索组件。

您的新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,可以看到两种方法。