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

问题描述 投票:3回答:1

我需要在我的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";
...

我该如何实现?

javascript reactjs ecmascript-6 components es6-modules
1个回答
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,可以看到两种方法。

© www.soinside.com 2019 - 2024. All rights reserved.