Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Too many React Context providers

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?

like image 973
jonhobbs Avatar asked Jul 24 '18 17:07

jonhobbs


2 Answers

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.

like image 104
rista404 Avatar answered Sep 29 '22 18:09

rista404


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> 
like image 26
Milan Majer Avatar answered Sep 29 '22 18:09

Milan Majer