React Context提供程序过多

时间:2018-07-24 17:31:07

标签: reactjs react-context

在这里做出新反应并尝试将我的头缠在新的Context API上(我还没有研究过Redux等。)

似乎我可以做很多我想做的事,但最终我会得到很多提供商,所有提供商都需要一个标签来包装我的主应用程序。

我将为Auth提供一个提供程序,一个为主题提供服务,一个为聊天消息提供服务(通过Pusher.com访问),等等。另外,使用React Router的还有另一个包装元素。

我要结束这个(还有更多)吗?...

<BrowserRouter>
    <AuthProvider>
        <ThemeProvider>
            <ChatProvider>
                <App />
            </ChatProvider>
        </ThemeProvider>
    </AuthProvider>
</BrowserRouter>

还是有更好的方法?

6 个答案:

答案 0 :(得分:1)

免责声明:我从未使用过,只是进行了研究。

FormidableLabs(他们为许多OSS projects做出了贡献)有一个名为react-context-composer

的项目

似乎可以解决您的问题。

  

React正在提出一个新的Context API。 API鼓励撰写。   该实用程序组件有助于在组件保持代码清洁   将呈现多个上下文提供者和使用者。

答案 1 :(得分:1)

如果您想要一种无需任何第三方库即可组成Provider的解决方案,请使用带有Typescript批注的解决方案:

// Compose.tsx

interface Props {
    components: Array<React.JSXElementConstructor<React.PropsWithChildren<any>>>
    children: React.ReactNode
}

export default function Compose(props: Props) {
    const { components = [], children } = props

    return (
        <>
            {components.reduceRight((acc, Comp) => {
                return <Comp>{acc}</Comp>
            }, children)}
        </>
    )
}

用法:

<Compose components={[BrowserRouter, AuthProvider, ThemeProvider, ChatProvider]}>
    <App />
</Compose>

如果您不使用Typescript,当然可以删除注释。

答案 2 :(得分:0)

一个简单的解决方案是使用类似于compose函数的方法  https://github.com/reduxjs/redux/blob/master/src/compose.js,并将所有提供程序合并在一起。

provider.js

const Providers = compose(
    AuthProvider,
    ThemeProvider,
    ChatProvider
);

我还没有使用这个解决方案,但是有了React的新钩子功能,您可以使用react钩子在函数定义中访问它,而不是呈现您的上下文。

答案 3 :(得分:0)

很少的代码行可以解决您的问题。

import React from "react"
import _ from "lodash"

/**
 * Provided that a list of providers [P1, P2, P3, P4] is passed as props,
 * it renders
 *
 *    <P1>
        <P2>
          <P3>
            <P4>
              {children}
            </P4>
          </P3>
        </P2>
      </P1>
 *
 */

export default function ComposeProviders({ Providers, children }) {
  if (_.isEmpty(Providers)) return children

  return _.reverse(Providers)
    .reduce((acc, Provider) => {
      return <Provider>{acc}</Provider>
    }, children)
}

答案 4 :(得分:0)

使用for循环的解决方案:

export const provider = (provider, props = {}) => [provider, props];

export const ProviderComposer = ({providers, children}) => {
    for (let i = providers.length - 1; i >= 0; --i) {
        const [Provider, props] = providers[i];
        children = <Provider {...props}>{children}</Provider>
    }
    return children;
}

用法:

<ProviderComposer
    providers={[
        provider(AuthProvider),
        provider(ThemeProvider),
        provider(MuiPickersUtilsProvider, {utils: DateFnsUtils}),
    ]}
>
    <App/>
</ProviderComposer>

答案 5 :(得分:0)

如果需要将外部 props 注入到 provider elemet 使用 withprops hoc,请重新编写 js 嵌套助手