Too many React Context providers

前端 未结 5 1822
渐次进展
渐次进展 2021-01-31 17:39

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

相关标签:
5条回答
  • 2021-01-31 18:03

    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.

    0 讨论(0)
  • 2021-01-31 18:13

    Solution with for loop:

    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;
    }
    

    Usage:

    <ProviderComposer
        providers={[
            provider(AuthProvider),
            provider(ThemeProvider),
            provider(MuiPickersUtilsProvider, {utils: DateFnsUtils}),
        ]}
    >
        <App/>
    </ProviderComposer>
    
    0 讨论(0)
  • 2021-01-31 18:18

    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.

    0 讨论(0)
  • 2021-01-31 18:22

    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)
    }
    
    0 讨论(0)
  • 2021-01-31 18:24

    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.

    0 讨论(0)
提交回复
热议问题