"Anonymous" HTML 元素在整合 React Providers 时添加

"Anonymous" HTML elements added while consolidating React Providers

我正在尝试通过使用函数注入嵌套的提供程序数组来整理我的 App.js 文件。

以前我有一些东西看起来像:

 <CreditsProvider>
   <BundlesProvider>
     <ContactsProvider>
       <PhoneVerificationProvider>
          <PurchaseProvider>
            <RanksProvider>
              <RoleWizardProvider>
                 <BasesProvider>
                   <DepsProvider>
                     <TitlesProvider>
                        <UrlsProvider>
                           <Main />
                        </UrlsProvider>
                      </TitlesProvider>
                    </DepsProvider>
                  </BasesProvider>
                </RoleWizardProvider>
              </RanksProvider>
            </PurchaseProvider>
          </PhoneVerificationProvider>
        </ContactsProvider>
      </BundlesProvider>
   </CreditsProvider>

我构建了一个自动执行此操作的函数:

export function BuildProviderTree(providers) {
    if (providers.length === 1) {
        return providers[0];
    }
    const A = providers.shift();
    const B = providers.shift();
    return BuildProviderTree([
        ({ children }) => (
            <A>
                <B>{children}</B>
            </A>
        ),
        ...providers,
    ]);
}

回到 App.js,我向供应商列表中的函数收费,并将其添加到我的应用程序中。

const Providers = BuildProviderTree(
    ...[
        HeaderBarProvider,
        CreditsProvider,
        BundlesProvider,
        ContactsProvider,
        PhoneVerificationProvider,
        PurchaseProvider,
        RanksProvider,
        RoleWizardProvider,
        BasesProvider,
        DepsProvider,
        TitlesProvider,
        UrlsProvider,
    ]
);

<NotificationBarProvider>
  <NotificationBar />
  <Providers>
     <Main />
  </Providers>
</NotificationBarProvider>

一切正常,但是当我使用我的 React 开发工具检查组件结构时,我注意到一堆嵌套的匿名元素。

我曾尝试按照评论中的说明更改我的出口申报,但没有成功。

当我进一步挖掘时,我注意到所有匿名元素都来自函数中的 <A> 元素,而命名提供者是 <B> 元素。

匿名函数是您的 ({ children }) => ( ... ) 函数。

分析

  1. 应用第一个和第二个组件(HeaderBarProviderCreditsProvider)后,新数组如下所示:
[
    ({ children }) => ( // <-- Anonymous function, new 1st element of array, will be `A` the next time
        <HeaderBarProvider>     // `A`
            <CreditsProvider>   // `B`
                { children }
            </CreditsProvider>
        </HeaderBarProvider>
    ),
    BundlesProvider, // <-- second element of array, will be `B` the next time
    ContactsProvider,
    PhoneVerificationProvider,
    // ...
]
  1. 应用前一个和第三个组件 (BundlesProvider) 后,新数组如下所示:
[
    ({ children }) => (       // <-- Anonymous (new first element of the array)
        ({ children }) => (   // <-- Anonymous (was previously the first element of the array)
            <HeaderBarProvider>
                <CreditsProvider>
                    <BundlesProvider>
                        { children }
                    </BundlesProvider>
                </CreditsProvider>
            </HeaderBarProvider>
        )
    ),
    ContactsProvider,         // <-- new second element of array
    PhoneVerificationProvider,
    // ...
]

可能的解决方案

您应该知道在“React 构建时”(创建组件时)发生了什么, 以及在“React 运行 时间”发生了什么(当 React 从组件创建元素时)。
(术语“构建时间”和“运行 时间”在这里可能不准确)

  • 你的匿名函数,又名。 React 组件 在“构建时”创建
  • React Elements <A><B> 是在“运行 时间”创建的

使用您的方法 - 创建一个 HOC(高阶组件)以在“构建时”一次组合 2 个组件 - 您无法避免创建这些包装函数。 你不能改变函数(即组件)的样子,所以唯一的方法是创建一个 new 组件,用 original 组件包装起来修改道具。 new 组件就是那个匿名函数。

可以做的是您可以在“运行 时间”定义组件应如何呈现为元素。 IE。您可以在 运行 时编写 Elements,而不是在构建时编写 Components。所以你只需要一个 HOC,它创建元素:

export function BuildProviderTreeAtRuntime(originalProviders) {

    const compose = function(providers, children){
        if( providers.length < 1 ){
            return children;
        } else {
            const CurrentComponent = providers.pop();
            return compose(
                providers,
                <CurrentComponent key={'id_' + providers.length + '_' + CurrentComponent.name}>{ children }</CurrentComponent>
            );
        }
    }

    return function ComposedElements({ children }){ // <-- only one wrapper function (HOC), which creates all the nested elements
        const providers = [ ...originalProviders ];
        return compose(providers, children);
    };
}