Skip to content

Instantly share code, notes, and snippets.

@stolinski
Created April 23, 2019 17:40
Show Gist options
  • Star 61 You must be signed in to star a gist
  • Fork 11 You must be signed in to fork a gist
  • Save stolinski/2d9545e19dd67bda64143cb1aae04ac0 to your computer and use it in GitHub Desktop.
Save stolinski/2d9545e19dd67bda64143cb1aae04ac0 to your computer and use it in GitHub Desktop.
ProviderComposer
function ProviderComposer({ contexts, children }) {
return contexts.reduceRight(
(kids, parent) =>
React.cloneElement(parent, {
children: kids,
}),
children
);
}
function ContextProvider({ children }) {
return (
<ProviderComposer
contexts={[<CheckoutProvider />, <LoginProvider />, <AlertProvider />]}
>
{children}
</ProviderComposer>
);
}
export { ContextProvider };
@tomekrozalski
Copy link

Nice, but I have an issue: the providers (CheckoutProvider, LoginProvider and so on) are JSX components which requires children as props, isn't it? And here, in line 15 we are calling these providers without props. This makes our console looking bad ;) Yes, I know we can set defaultProps of providers to children: null, but it smells. It would be great if we could pass to context array (line 15) just providers as functions (contexts={[CheckoutProvider, LoginProvider, AlertProvider]})… The snippet is great anyway! Thanks for sharing :)

@nghiatv
Copy link

nghiatv commented Apr 22, 2020

I have same question as @tomekrozalski. So what is the answer here?

@tomekrozalski
Copy link

@nghiatv I believe it is just linting / console / I don't know issue. On my next projects I didn't have this warning again. Now I use TypeScript and it does not complain at all for this script :)

@Alfrex92
Copy link

Does anyone have the Typescript version of this snippet?

@tomekrozalski
Copy link

@Alfrex92 I just use any:

type Props = {
  contexts: any;
};

const ProviderComposer: React.FC<Props> = ({ contexts, children }) =>
  contexts.reduceRight(
    (kids: React.ReactNode, parent: any) =>
      React.cloneElement(parent, {
        children: kids,
      }),
    children,
  );

const GlobalStateProvider: React.FC = ({ children }) => (
  <ProviderComposer contexts={[<Navigation />, <Authentication />, <Search />]}>
    {children}
  </ProviderComposer>
);

@Alfrex92
Copy link

thanks!

@islami00
Copy link

islami00 commented Feb 25, 2022

This is excellent. I had no idea one huge tree would cause unnecessary renders. This removes one step from moving things to global state, and it also makes global state really similar to local state! Thanks.

this way all one has to do is useContext(SomeGlobalImport). Much cleaner than my initial idea of lookups. More direct and simplified too!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment