Skip to content

Commit

Permalink
Compose React Providers without nesting
Browse files Browse the repository at this point in the history
  • Loading branch information
brunolemos committed Jun 23, 2021
1 parent 4564e05 commit 2d018ea
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 31 deletions.
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ module.exports = {
'@typescript-eslint/unbound-method': 'warn',
'no-console': ['warn', { allow: ['warn', 'error'] }],
'react/display-name': 'warn',
'react/no-children-prop': 'off',
'react/no-find-dom-node': 'off',
},
}
56 changes: 26 additions & 30 deletions packages/components/src/components/AppProviders.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { LoginHelpersProvider } from './context/LoginHelpersContext'
import { AppLayoutProvider } from './context/LayoutContext'
import { PlansProvider } from './context/PlansContext'
import { ThemeProvider } from './context/ThemeContext'
import { Compose } from './common/Compose'

const { persistor, store } = configureStore()

Expand All @@ -25,35 +26,30 @@ export interface AppProvidersProps {

export function AppProviders(props: AppProvidersProps) {
return (
<HelmetProvider>
<ReduxProvider store={store as any}>
<PersistGate loading={null} persistor={persistor}>
<AppearanceProvider>
<ThemeProvider>
<SafeAreaProvider>
<DialogProvider>
<DeepLinkProvider>
<PlansProvider>
<AppLayoutProvider>
<ColumnFocusProvider>
<ColumnWidthProvider>
<ColumnFiltersProvider>
<LoginHelpersProvider>
{props.children}
</LoginHelpersProvider>
<OverrideSystemDialog />
</ColumnFiltersProvider>
</ColumnWidthProvider>
</ColumnFocusProvider>
</AppLayoutProvider>
</PlansProvider>
</DeepLinkProvider>
</DialogProvider>
</SafeAreaProvider>
</ThemeProvider>
</AppearanceProvider>
</PersistGate>
</ReduxProvider>
</HelmetProvider>
<Compose
components={[
(child) => <HelmetProvider children={child} />,
(child) => <ReduxProvider children={child} store={store} />,
(child) => (
<PersistGate children={child} loading={null} persistor={persistor} />
),
(child) => <AppearanceProvider children={child} />,
(child) => <ThemeProvider children={child} />,
(child) => <SafeAreaProvider children={child} />,
(child) => <DialogProvider children={child} />,
(child) => <DeepLinkProvider children={child} />,
(child) => <PlansProvider children={child} />,
(child) => <AppLayoutProvider children={child} />,
(child) => <ColumnFocusProvider children={child} />,
(child) => <ColumnWidthProvider children={child} />,
(child) => <ColumnFiltersProvider children={child} />,
(child) => <LoginHelpersProvider children={child} />,
]}
>
<>
{props.children}
<OverrideSystemDialog />
</>
</Compose>
)
}
25 changes: 25 additions & 0 deletions packages/components/src/components/common/Compose.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React from 'react'

type PropsWithChildren = { [key: string]: any; children: any }

type ComposableFunction = (
child: React.ComponentElement<PropsWithChildren, any>,
) => React.ComponentElement<PropsWithChildren, any>

interface ComposeProps {
components: ComposableFunction[]
children: React.ReactNode
}

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

return (
<>
{components.reduceRight<React.ComponentElement<PropsWithChildren, any>>(
(result, item) => item(result),
children as any,
)}
</>
)
}
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@
"module": "esnext"
},
"exclude": ["node_modules"],
"include": ["@types", "landing", "packages"]
"include": ["@types", "landing", "packages", ".eslintrc.js"]
}

0 comments on commit 2d018ea

Please sign in to comment.