๐บ Flat React Doom Pyramid in 1LOC
Every React app I opened had the same thing at its root: a pyramid of context providers, each one nested inside the last. It works, but itโs hard to read and painful to reorder. It turns out you can flatten it with a single line.
Everyone was happy when React Team announced the new stable Context API, and everyone ditched Redux. But thatโs not the point.
After 1 year every codebase entrypoint looked like this at least.
<I18nProvider>
<DataProvider>
<ActiveDialogProvider>
<PublicFetchProvider>
<AuthProvider>
<PrivateFetchProvider>
<AuthFetchProvider>
<CustomThemeProvider>
<CustomMuiPickersUtilsProvider>
<LegalsProvider>
<PaymentMethodsProvider>
<CartProvider>
<App />
</CartProvider>
</PaymentMethodsProvider>
</LegalsProvider>
</CustomMuiPickersUtilsProvider>
</CustomThemeProvider>
</AuthFetchProvider>
</PrivateFetchProvider>
</AuthProvider>
</PublicFetchProvider>
</ActiveDialogProvider>
</DataProvider>
</I18nProvider>

Soooo, should we do something about this? Most of the times there is no reason. Nevertheless, here is a simple performant solution in 1 line of code
const Pipe = (p) =>
p.children.reduceRight((c, e) => ({
...e,
props: { ...e.props, children: c },
}));
You can name it however you want:
- Flatten
- Compose
- Pipe
- Squash
- Doom ๐
- Nest
- Inflate
And how will look above example? Better!
<Pipe>
<I18nProvider />
<DataProvider />
<ActiveDialogProvider />
<PublicFetchProvider />
<AuthProvider />
<PrivateFetchProvider />
<AuthFetchProvider />
<CustomThemeProvider />
<CustomMuiPickersUtilsProvider />
<LegalsProvider />
<PaymentMethodsProvider />
<CartProvider />
<App />
</Pipe>
This function component takes all its children and nests them from first to last, where first one will be the most outside the tree, and the last one will be last in the tree.
Here is one more variation with TypeScript and different API
function Flatten(props: PropsWithChildren<{ elements: ReactElement[] }>) {
const { elements: e, children: init } = props;
return (
<>{e.reduceRight((c, e) => cloneElement(e, { children: c }), init)}</>
);
}
And the usage will be like this:
<Flatten
elements={[
<I18nProvider />,
<DataProvider />,
<ActiveDialogProvider />,
<PublicFetchProvider />,
<AuthProvider />,
<PrivateFetchProvider />,
<AuthFetchProvider />,
<CustomThemeProvider />,
<CustomMuiPickersUtilsProvider />,
<LegalsProvider />,
<PaymentMethodsProvider />,
<CartProvider />,
]}
>
<App />
</Flatten>
I went through multiple iterations, and in the end I prefer first Pipe one liner that I showed.
Sandboxes experiments:
- https://codesandbox.io/s/react-flatten-pyramid-wpr7o
- https://codesandbox.io/s/react-flatten-pyramid-benchs-wgyhf
- https://codesandbox.io/s/react-flatten-pyramid-benchs-clean-o82xw
Thanks for coming to my TED talk! :)

- Created At
- 9/22/2021
- Updated At
- 12/17/2022
- Published At
- 9/22/2021