Skip to content

Instantly share code, notes, and snippets.

@kate0n
Last active January 5, 2023 15:33
Show Gist options
  • Select an option

  • Save kate0n/c45da830d0dd52004454612be8b9e98e to your computer and use it in GitHub Desktop.

Select an option

Save kate0n/c45da830d0dd52004454612be8b9e98e to your computer and use it in GitHub Desktop.
Compose React context providers

Example

See it in action at https://codesandbox.io/s/n6txl.

The Problem

Have you ever come across a tree like this:

<ContextA.Provider>
  <ContextB.Provider>
    <ContextC.Provider>
      ...
    </ContextC.Provider>
  </ContextB.Provider>
</ContextA.Provider>

Instead, we can compose/combine this list of providers:

<Compose items={[
  [ContextA, props],
  [ContextB, props],
  [ContextC, props],
]}>
  ...
</Compose>

Example 2

const AppProvider = compose(OneProvider, TwoProvider);


function OneProvider({ children }) {
  return <div>2:{children}</div>;
}

function TwoProvider({ children }) {
  return <div>1:{children}</div>;
}


function compose(...providers) {
  return function Composed({ children }) {
    return providers.reduce((child, Element) => {
      return <Element>{child}</Element>;
    }, children);
  };
}
import React from "react";
import Compose from "./Compose.js";
import Context from "./Context.js";
export default function App() {
const [foo] = React.useState(1);
const [bar] = React.useState(2);
return (
<Compose
items={[
[Context, { foo, bar }],
]}
>
<Context.Consumer />
</Compose>
);
}
import React from "react";
export default function Compose({ items, children }) {
return items.reduceRight(
(acc, [Context, props]) =>
React.createElement(Context.Provider, props, acc),
children
);
}
import React from "react";
const Context = React.createContext();
function Consumer() {
const value = React.useContext(Context);
return <pre>Value: {JSON.stringify(value)}</pre>;
// Value: {"foo":1,"bar":2}
}
function Provider({ children, ...props }) {
return <Context.Provider value={props}>{children}</Context.Provider>;
}
export default { Context, Provider, Consumer };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment