-
Notifications
You must be signed in to change notification settings - Fork 2.7k
/
ComponentWrapper.tsx
88 lines (77 loc) · 2.76 KB
/
ComponentWrapper.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import * as React from 'react';
import { ComponentProvider } from 'react-native';
import * as _ from 'lodash';
import { polyfill } from 'react-lifecycles-compat';
import hoistNonReactStatics = require('hoist-non-react-statics');
import { Store } from './Store';
import { ComponentEventsObserver } from '../events/ComponentEventsObserver';
interface HocState { componentId: string; allProps: {}; }
interface HocProps { componentId: string; }
export interface IWrappedComponent extends React.Component {
setProps(newProps: Record<string, any>): void;
}
export class ComponentWrapper {
wrap(
componentName: string | number,
OriginalComponentGenerator: ComponentProvider,
store: Store,
componentEventsObserver: ComponentEventsObserver,
concreteComponentProvider: ComponentProvider = OriginalComponentGenerator,
ReduxProvider?: any,
reduxStore?: any
): React.ComponentClass<any> {
const GeneratedComponentClass = OriginalComponentGenerator();
class WrappedComponent extends React.Component<HocProps, HocState> {
static getDerivedStateFromProps(nextProps: any, prevState: HocState) {
return {
allProps: _.merge({}, nextProps, store.getPropsForId(prevState.componentId))
};
}
constructor(props: HocProps) {
super(props);
this._assertComponentId();
this.state = {
componentId: props.componentId,
allProps: {}
};
store.setComponentInstance(props.componentId, this);
}
public setProps(newProps: any) {
this.setState({allProps: newProps});
}
componentWillUnmount() {
store.clearComponent(this.state.componentId);
componentEventsObserver.unmounted(this.state.componentId);
}
render() {
return (
<GeneratedComponentClass
{...this.state.allProps}
componentId={this.state.componentId}
/>
);
}
private _assertComponentId() {
if (!this.props.componentId) {
throw new Error(`Component ${componentName} does not have a componentId!`);
}
}
}
polyfill(WrappedComponent);
hoistNonReactStatics(WrappedComponent, concreteComponentProvider());
return ReduxProvider ? this.wrapWithRedux(WrappedComponent, ReduxProvider, reduxStore) : WrappedComponent;
}
wrapWithRedux(WrappedComponent: React.ComponentClass<any>, ReduxProvider: any, reduxStore: any): React.ComponentClass<any> {
class ReduxWrapper extends React.Component<any, any> {
render() {
return (
<ReduxProvider store={reduxStore}>
<WrappedComponent {...this.props} />
</ReduxProvider>
);
}
}
hoistNonReactStatics(ReduxWrapper, WrappedComponent);
return ReduxWrapper;
}
}