React Provider Hell
React Provider Hell
#Issue
const context1 = createContext({});
const context2 = createContext({});
const context3 = createContext({});
const context4 = createContext({});
const ChildApp = () => {
  const v1 = useContext(context1);
  const v2 = useContext(context2);
  const v3 = useContext(context3);
  const v4 = useContext(context4);
  return (
    <>
      <h2>ChildApp</h2>
      {v1.v}
      {v2.v}
      {v3.v}
      {v4.v}
    </>
  );
};
const App = () => {
  return (
    <>
      <context1.Provider value={{ v: 1 }}>
        <context2.Provider value={{ v: 2 }}>
          <context3.Provider value={{ v: 3 }}>
            <context4.Provider value={{ v: 4 }}>
              <ChildApp />
            </context4.Provider>
          </context3.Provider>
        </context2.Provider>
      </context1.Provider>
    </>
  );
};
render(<App />);
    jsx
    
  #Solution
const context1 = createContext({});
const context2 = createContext({});
const context3 = createContext({});
const context4 = createContext({});
const ChildApp = () => {
  const v1 = useContext(context1);
  const v2 = useContext(context2);
  const v3 = useContext(context3);
  const v4 = useContext(context4);
  return (
    <>
      <h2>ChildApp</h2>
      {v1.v}
      {v2.v}
      {v3.v}
      {v4.v}
    </>
  );
};
import { cloneElement, memo } from 'react';
export interface ContextComposeProviderProps extends React.PropsWithChildren {
  contexts: React.ReactElement[]
}
export const ComposeContextProvider = memo(({
  contexts,
  children
}: ContextComposeProviderProps) => contexts.reduceRight<React.ReactNode>(
  (children: React.ReactNode, parent) => cloneElement(
    parent,
    { children }
  ),
  children
));
const contexts = [
   context1.Provider value={{ v: 1 }} />,
  <context2.Provider value={{ v: 2 }} />,
  <context3.Provider value={{ v: 3 }} />,
  <context4.Provider value={{ v: 4 }} />,
];
const App = () => {
  return (
    <>
      <ComposeContextProvider contexts={contexts}>
        <ChildApp />
      </ComposeContextProvider>
    </>
  );
};
    jsx
    
  
