This article gives you a way to convert your tree of React Context Provider components into a flat structure.
Many React application with multiple contexts end up with a deep nested tree of context providers, something like this:
const AppWithProviders = () => (
<ThemeContext.Provider>
<UserContext.Provider>
<SomeOtherContext.Provider>
<YetAnotherContext.Provider>
<OneMoreContext.Provider>
<AndOneMoreContext.Provider>
<AndSoOnContext.Provider>
<AndSoForthContext.Provider>
<App/>
</AndSoForthContext.Provider>
</AndSoOnContext.Provider>
</AndOneMoreContext.Provider>
</OneMoreContext.Provider>
</YetAnotherContext.Provider>
</SomeOtherContext.Provider>
</UserContext.Provider>
</ThemeContext.Provider>
)
In my company we have more than 20 such levels and the app is far from completion!
To make the structure more flat you can use this function:
const BuildProviderTree = (providers) => {
if (providers.length === 1) {
return providers[0];
}
const A = providers.shift();
const B = providers.shift();
return BuildProviderTree([
({ children }) => (
<A>
<B>
{children}
</B>
</A>
),
...providers,
]);
};
Then redefine AppWithProviders
function like this:
const Providers = BuildProviderTree([
ThemeContext.Provider,
UserContext.Provider,
SomeOtherContext.Provider,
YetAnotherContext.Provider,
OneMoreContext.Provider,
AndOneMoreContext.Provider,
AndSoOnContext.Provider,
AndSoForthContext.Provider,
]);
const AppWithProviders = () => (
<Providers>
<App/>
</Providers>
);
Nice and flat!
Update. I have released an NPM package for that: react-array-to-tree. It also supports component attributes:
const Providers = BuildProviderTree([
[ThemeContext.Provider, {param1: value1, param2: value2},
[UserContext.Provider],
[SomeOtherContext.Provider],
]);
will be converted to
<ThemeContext.Provider param1=value1 param2=value2>
<UserContext.Provider>
<SomeOtherContext.Provider>
...
</SomeOtherContext.Provider>
</UserContext.Provider>
</ThemeContext.Provider>