import * as React from 'react'; import * as _ from 'lodash'; import * as ReactLifecyclesCompat from 'react-lifecycles-compat'; export class ComponentWrapper { static wrap(componentName: string, OriginalComponentClass: React.ComponentType, store): React.ComponentType { class WrappedComponent extends React.Component { static getDerivedStateFromProps(nextProps, prevState) { return { allProps: _.merge({}, nextProps, store.getPropsForId(prevState.componentId)) }; } private originalComponentRef; constructor(props) { super(props); this._assertComponentId(); this._saveComponentRef = this._saveComponentRef.bind(this); this.state = { componentId: props.componentId, allProps: {} }; } componentDidMount() { store.setRefForId(this.state.componentId, this); } componentWillUnmount() { store.cleanId(this.state.componentId); } componentDidAppear() { if (this.originalComponentRef.componentDidAppear) { this.originalComponentRef.componentDidAppear(); } } componentDidDisappear() { if (this.originalComponentRef.componentDidDisappear) { this.originalComponentRef.componentDidDisappear(); } } onNavigationButtonPressed(buttonId) { if (this.originalComponentRef.onNavigationButtonPressed) { this.originalComponentRef.onNavigationButtonPressed(buttonId); } } onSearchBarUpdated(text, isFocused) { if (this.originalComponentRef.onSearchBarUpdated) { this.originalComponentRef.onSearchBarUpdated(text, isFocused); } } render() { return ( ); } private _assertComponentId() { if (!this.props.componentId) { throw new Error(`Component ${componentName} does not have a componentId!`); } } private _saveComponentRef(r) { this.originalComponentRef = r; } } ReactLifecyclesCompat.polyfill(WrappedComponent); require('hoist-non-react-statics')(WrappedComponent, OriginalComponentClass); return WrappedComponent; } }