Skip to content

Instantly share code, notes, and snippets.

@nielsboecker
Last active July 27, 2019 15:17
Show Gist options
  • Save nielsboecker/a0e59ccab8449796bc566809ce019139 to your computer and use it in GitHub Desktop.
Save nielsboecker/a0e59ccab8449796bc566809ce019139 to your computer and use it in GitHub Desktop.
TypeScript HOC (Higher-Order Component) for wrapping React components with context consumers
// Usage in other components
import { PropsWithContext, withAppContext } from "./WithAppContext";
export interface ISomeComponentProps extends PropsWithContext {
otherProp: string;
}
class SomeComponent extends Component<ISomeComponentProps> {
// or: can also extend Component<PropsWithContext> or extend Component<SomeProps & PropsWithContext>
render() {
console.log(this.props.context);
// ...
}
export default withAppContext(SomeComponent);
// Definition of HOC, could be placed in same file where you createContext()
export type ComponentPropsWithContext = { context?: IAppState };
/**
* @deprecated This caused problems for components that access props.children
*/
export function withAppContextOld<
OutProps extends ComponentPropsWithContext,
InProps = Omit<OutProps, "context">
>(Component: ComponentType<InProps>) {
return (props: InProps) => (
<AppContext.Consumer>
{(context: IAppState) => <Component {...props} context={context} />}
</AppContext.Consumer>
);
}
/**
* Higher-order component to wrap an arbitrary component and provide it with app context.
*
* @param InnerComponent the component to wrap
* @param pureComponent whether to return a PureComponent (use false if InnerComponent uses other
* props and fails to update properly due to PureComponent's flat diffs)
*/
export const withAppContext = <ComponentProps extends {}>(
InnerComponent: ComponentType<ComponentProps>,
pureComponent: boolean = true
) => {
const componentType = pureComponent ? PureComponent : Component;
return class WithContext extends componentType<ComponentProps & PropsWithContext> {
render() {
return (
<AppContext.Consumer>
{(context: IAppState) => <InnerComponent {...this.props} context={context} />}
</AppContext.Consumer>
);
}
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment