Skip to content

Instantly share code, notes, and snippets.

@tylerthebuildor
Forked from etienne-dldc/combineContext.js
Created March 28, 2018 18:54
Show Gist options
  • Save tylerthebuildor/841c6b4ba8df37ec1100ef45137a343b to your computer and use it in GitHub Desktop.
Save tylerthebuildor/841c6b4ba8df37ec1100ef45137a343b to your computer and use it in GitHub Desktop.
A small function to combine react Contexts.
import React from 'react';
function onlyChild(children) {
return Array.isArray(children) ? children[0] : children;
}
export function combineContext(contexts) {
class Provider extends React.Component {
render() {
const init = this.props.children;
return Object.keys(contexts).reduce((acc, contextName) => {
const TheContext = contexts[contextName];
return <TheContext.Provider value={this.props.value[contextName]}>{acc}</TheContext.Provider>;
}, init);
}
}
class Consumer extends React.Component {
render() {
const init = (value) => onlyChild(this.props.children)(value);
const renderer = Object.keys(contexts).reduce((acc, contextName) => {
const TheContext = contexts[contextName];
return (value) => (
<TheContext.Consumer>
{contextValue => {
return acc({
...value,
[contextName]: contextValue,
});
}}
</TheContext.Consumer>
);
}, init);
return renderer({});
}
}
return {
Consumer,
Provider,
};
}
import * as React from 'react';
import { ConsumerProps, Context, ProviderProps } from 'create-react-context';
function onlyChild(children: any): any {
return Array.isArray(children) ? children[0] : children;
}
export function combineContext<In extends { [key: string]: any }>(
contexts: { [K in keyof In]: Context<In[K]> }
): Context<{ [K in keyof In]: In[K] }> {
class Provider extends React.Component<ProviderProps<{ [K in keyof In]: In[K] }>> {
render() {
const init = this.props.children;
return Object.keys(contexts).reduce((acc, contextName) => {
const TheContext = contexts[contextName];
return <TheContext.Provider value={this.props.value[contextName]}>{acc}</TheContext.Provider>;
}, init);
}
}
class Consumer extends React.Component<ConsumerProps<{ [K in keyof In]: In[K] }>> {
render() {
const init = (value: { [K in keyof In]: In[K] }) => onlyChild(this.props.children)(value);
const renderer = Object.keys(contexts).reduce<(value: { [K in keyof In]: In[K] }) => any>((acc, contextName) => {
const TheContext = contexts[contextName];
return (value: { [K in keyof In]: In[K] }) => (
<TheContext.Consumer>
{contextValue => {
return acc({
...(value as any),
[contextName]: contextValue,
});
}}
</TheContext.Consumer>
);
}, init);
return renderer({} as any);
}
}
return {
Consumer,
Provider,
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment