import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; import { R, React } from './common'; import { IStore } from './types'; import { Connector, ConnectorLoadedEvent } from './components/Connector'; interface IConnectWrapperState { store?: IStore; } export interface IConnectProps { store?: IStore; } /** * HoC factory for connecting a component to a store. */ export function connect

( component: React.SFC | React.ComponentClass | string, options: { autoRender?: boolean; path?: string; } = {}, ): React.ComponentClass

{ // Options. const autoRender = options.autoRender === undefined ? true : options.autoRender; // HoC. class ConnectWrapper extends React.PureComponent< P & IConnectProps, IConnectWrapperState > { private loaded: ConnectorLoadedEvent; public state: IConnectWrapperState = {}; private unmounted$ = new Subject(); private get store(): IStore | undefined { if (this.props.store) { // An explicit store was passed in as prop, use this instead of the one from the . return this.props.store; } // Read store that was passed via the . const store = this.loaded && this.loaded.store; const { path } = options; const result = path ? store.get(path) : store; return R.is(Object, result) ? result : undefined; } private init = (e: ConnectorLoadedEvent) => { this.loaded = e; }; public componentDidMount() { const store = this.store; this.setState({ store }); if (store && autoRender) { store.state$.pipe(takeUntil(this.unmounted$)).subscribe(() => { try { this.forceUpdate(); } catch (error) { this.unmounted$.next(); } }); } } public componentWillUnmount() { this.unmounted$.next(); } public render() { return ( {this.renderComponent()} ); } private renderComponent() { const { store } = this.state; if (!store) { // Don't render anything if the store has not been retrieved yet. // Ensure the first render of the component has a store. return ''; } const props: any = { ...(this.props as object), store, }; return React.createElement(component, props); } } // Finish up. return ConnectWrapper as React.ComponentClass

; }