Too many React Context providers

天涯浪子 提交于 2020-07-31 07:31:52

问题


New to react here and trying to wrap my head round the new Context API (I haven't looked into Redux etc. yet).

Seems I can do much of what I need to do, but I'm going to end up with lots and lots of providers, all needing a tag to wrap my main app.

I'm going to have a provider for Auth, one for theming, one for chat messages (vis Pusher.com) etc. Also using React Router is another wrapper element.

Am I going to have to end up with this (and many more)....

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

Or is there a better way?


回答1:


Use @rista404's answer - https://stackoverflow.com/a/58924810/4035
as react-context-composer is deprecated.

Thanks @AO17, for the ping.


Disclaimer: I've never used this, just researched.

FormidableLabs (they contribute to many OSS projects) has a project called, react-context-composer

It seems to solve your issue.

React is proposing a new Context API. The API encourages composing. This utility component helps keep your code clean when your component will be rendering multiple Context Providers and Consumers.




回答2:


If you want a solution for composing Providers without any third-party libraries, here's one with Typescript annotations:

// 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)}
        </>
    )
}

Usage:

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

You can of course remove the annotations if you don't use Typescript.




回答3:


Few lines of code solve your problem.

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:


One simple solution for this is to use something similar to compose function in https://github.com/reduxjs/redux/blob/master/src/compose.js and combine all the providers together.

provider.js

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

also I haven't used this solution but with React's new hooks feature, instead of rendering your contexts, you can use the react hook to access it in the function definition.



来源:https://stackoverflow.com/questions/51504506/too-many-react-context-providers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!