Browse Source

Avoid calling component generators on registerComponent (#4286)

* Avoid calling component generators on registerComponent

* fix unit tests

* remove console.log

* fix coverage

* fix coverage
Yogev Ben David 5 years ago
parent
commit
708d594877
No account linked to committer's email address

+ 4
- 4
docs/api/Store.md View File

@@ -16,17 +16,17 @@
16 16
 
17 17
 ---
18 18
 
19
-## setOriginalComponentClassForName
19
+## setComponentClassForName
20 20
 
21
-`setOriginalComponentClassForName(componentName: string, ComponentClass: any): void`
21
+`setComponentClassForName(componentName: string, ComponentClass: any): void`
22 22
 
23 23
 [source](https://github.com/wix/react-native-navigation/blob/v2/lib/src/components/Store.ts#L15)
24 24
 
25 25
 ---
26 26
 
27
-## getOriginalComponentClassForName
27
+## getComponentClassForName
28 28
 
29
-`getOriginalComponentClassForName(componentName: string): any`
29
+`getComponentClassForName(componentName: string): any`
30 30
 
31 31
 [source](https://github.com/wix/react-native-navigation/blob/v2/lib/src/components/Store.ts#L19)
32 32
 

+ 1
- 1
integration/redux/Redux.test.js View File

@@ -41,7 +41,7 @@ describe('redux support', () => {
41 41
         );
42 42
       }
43 43
     };
44
-    const CompFromNavigation = Navigation.registerComponent('ComponentName', () => HOC);
44
+    const CompFromNavigation = Navigation.registerComponent('ComponentName', () => HOC)();
45 45
 
46 46
     const tree = renderer.create(<CompFromNavigation componentId='componentId' renderCountIncrement={renderCountIncrement}/>);
47 47
     expect(tree.toJSON().children).toEqual(['no name']);

+ 1
- 1
integration/remx/remx.test.js View File

@@ -48,7 +48,7 @@ describe('remx support', () => {
48 48
   it('support for static members in connected components', () => {
49 49
     expect(MyConnectedComponent.options).toEqual({ title: 'MyComponent' });
50 50
 
51
-    const registeredComponentClass = Navigation.registerComponent('MyComponentName', () => MyConnectedComponent);
51
+    const registeredComponentClass = Navigation.registerComponent('MyComponentName', () => MyConnectedComponent)();
52 52
     expect(registeredComponentClass.options).toEqual({ title: 'MyComponent' });
53 53
   });
54 54
 });

+ 6
- 4
lib/src/Navigation.ts View File

@@ -11,11 +11,11 @@ import { ComponentProvider } from 'react-native';
11 11
 import { Element } from './adapters/Element';
12 12
 import { CommandsObserver } from './events/CommandsObserver';
13 13
 import { Constants } from './adapters/Constants';
14
-import { ComponentType } from 'react';
15 14
 import { ComponentEventsObserver } from './events/ComponentEventsObserver';
16 15
 import { TouchablePreview } from './adapters/TouchablePreview';
17 16
 import { LayoutRoot, Layout } from './interfaces/Layout';
18 17
 import { Options } from './interfaces/Options';
18
+import { ComponentWrapper } from './components/ComponentWrapper';
19 19
 
20 20
 export class Navigation {
21 21
   public readonly Element: React.ComponentType<{ elementId: any; resizeMode?: any; }>;
@@ -31,15 +31,17 @@ export class Navigation {
31 31
   private readonly eventsRegistry: EventsRegistry;
32 32
   private readonly commandsObserver: CommandsObserver;
33 33
   private readonly componentEventsObserver: ComponentEventsObserver;
34
+  private readonly componentWrapper: typeof ComponentWrapper;
34 35
 
35 36
   constructor() {
36 37
     this.Element = Element;
37 38
     this.TouchablePreview = TouchablePreview;
38 39
     this.store = new Store();
40
+    this.componentWrapper = ComponentWrapper;
39 41
     this.nativeEventsReceiver = new NativeEventsReceiver();
40 42
     this.uniqueIdProvider = new UniqueIdProvider();
41 43
     this.componentEventsObserver = new ComponentEventsObserver(this.nativeEventsReceiver);
42
-    this.componentRegistry = new ComponentRegistry(this.store, this.componentEventsObserver);
44
+    this.componentRegistry = new ComponentRegistry(this.store, this.componentEventsObserver, this.componentWrapper);
43 45
     this.layoutTreeParser = new LayoutTreeParser();
44 46
     this.layoutTreeCrawler = new LayoutTreeCrawler(this.uniqueIdProvider, this.store);
45 47
     this.nativeCommandsSender = new NativeCommandsSender();
@@ -54,7 +56,7 @@ export class Navigation {
54 56
    * Every navigation component in your app must be registered with a unique name.
55 57
    * The component itself is a traditional React component extending React.Component.
56 58
    */
57
-  public registerComponent(componentName: string, getComponentClassFunc: ComponentProvider): ComponentType<any> {
59
+  public registerComponent(componentName: string, getComponentClassFunc: ComponentProvider): ComponentProvider {
58 60
     return this.componentRegistry.registerComponent(componentName, getComponentClassFunc);
59 61
   }
60 62
 
@@ -67,7 +69,7 @@ export class Navigation {
67 69
     getComponentClassFunc: ComponentProvider,
68 70
     ReduxProvider: any,
69 71
     reduxStore: any
70
-  ): ComponentType<any> {
72
+  ): ComponentProvider {
71 73
     return this.componentRegistry.registerComponent(componentName, getComponentClassFunc, ReduxProvider, reduxStore);
72 74
   }
73 75
 

+ 9
- 0
lib/src/commands/Commands.test.ts View File

@@ -254,6 +254,15 @@ describe('Commands', () => {
254 254
         children: []
255 255
       });
256 256
     });
257
+
258
+    it('calls component generator once', async () => {
259
+      const generator = jest.fn(() => {
260
+        return {};
261
+      });
262
+      store.setComponentClassForName('theComponentName', generator);
263
+      await uut.push('theComponentId', { component: { name: 'theComponentName' } });
264
+      expect(generator).toHaveBeenCalledTimes(1);
265
+    });
257 266
   });
258 267
 
259 268
   describe('pop', () => {

+ 39
- 6
lib/src/commands/LayoutTreeCrawler.test.ts View File

@@ -62,11 +62,44 @@ describe('LayoutTreeCrawler', () => {
62 62
     };
63 63
 
64 64
     const node: any = { type: LayoutType.Component, data: { name: 'theComponentName' } };
65
-    store.setOriginalComponentClassForName('theComponentName', MyComponent);
65
+    store.setComponentClassForName('theComponentName', () => MyComponent);
66 66
     uut.crawl(node);
67 67
     expect(node.data.options).toEqual(theStyle);
68 68
   });
69 69
 
70
+  it('Components: crawl does not cache options', () => {
71
+    const optionsWithTitle = (title) => {
72
+      return {
73
+        topBar: {
74
+          title: {
75
+            text: title
76
+          }
77
+        }
78
+      }
79
+    };
80
+
81
+    const MyComponent = class {
82
+      static options(props) {
83
+        return {
84
+          topBar: {
85
+            title: {
86
+              text: props.title
87
+            }
88
+          }
89
+        };
90
+      }
91
+    };
92
+
93
+    const node: any = { type: LayoutType.Component, data: { name: 'theComponentName', passProps: { title: 'title' } } };
94
+    store.setComponentClassForName('theComponentName', () => MyComponent);
95
+    uut.crawl(node);
96
+    expect(node.data.options).toEqual(optionsWithTitle('title'));
97
+
98
+    const node2: any = { type: LayoutType.Component, data: { name: 'theComponentName' } };
99
+    uut.crawl(node2);
100
+    expect(node2.data.options).toEqual(optionsWithTitle(undefined));
101
+  });
102
+
70 103
   it('Components: passes passProps to the static options function to be used by the user', () => {
71 104
     const MyComponent = class {
72 105
       static options(passProps) {
@@ -75,7 +108,7 @@ describe('LayoutTreeCrawler', () => {
75 108
     };
76 109
 
77 110
     const node: any = { type: LayoutType.Component, data: { name: 'theComponentName', passProps: { bar: { baz: { value: 'hello' } } } } };
78
-    store.setOriginalComponentClassForName('theComponentName', MyComponent);
111
+    store.setComponentClassForName('theComponentName', () => MyComponent);
79 112
     uut.crawl(node);
80 113
     expect(node.data.options).toEqual({ foo: 'hello' });
81 114
   });
@@ -88,7 +121,7 @@ describe('LayoutTreeCrawler', () => {
88 121
     };
89 122
 
90 123
     const node: any = { type: LayoutType.Component, data: { name: 'theComponentName' } };
91
-    store.setOriginalComponentClassForName('theComponentName', MyComponent);
124
+    store.setComponentClassForName('theComponentName', () => MyComponent);
92 125
     uut.crawl(node);
93 126
     expect(node.data.options).toEqual({ foo: {} });
94 127
   });
@@ -116,7 +149,7 @@ describe('LayoutTreeCrawler', () => {
116 149
     };
117 150
 
118 151
     const node = { type: LayoutType.Component, data: { name: 'theComponentName', options: passedOptions } };
119
-    store.setOriginalComponentClassForName('theComponentName', MyComponent);
152
+    store.setComponentClassForName('theComponentName', () => MyComponent);
120 153
 
121 154
     uut.crawl(node);
122 155
 
@@ -139,7 +172,7 @@ describe('LayoutTreeCrawler', () => {
139 172
     };
140 173
 
141 174
     const node: any = { type: LayoutType.Component, data: { name: 'theComponentName' } };
142
-    store.setOriginalComponentClassForName('theComponentName', MyComponent);
175
+    store.setComponentClassForName('theComponentName', () => MyComponent);
143 176
     uut.crawl(node);
144 177
     expect(node.data.options).not.toBe(theStyle);
145 178
   });
@@ -153,7 +186,7 @@ describe('LayoutTreeCrawler', () => {
153 186
     const MyComponent = class { };
154 187
 
155 188
     const node: any = { type: LayoutType.Component, data: { name: 'theComponentName' } };
156
-    store.setOriginalComponentClassForName('theComponentName', MyComponent);
189
+    store.setComponentClassForName('theComponentName', () => MyComponent);
157 190
     uut.crawl(node);
158 191
     expect(node.data.options).toEqual({});
159 192
   });

+ 1
- 1
lib/src/commands/LayoutTreeCrawler.ts View File

@@ -52,7 +52,7 @@ export class LayoutTreeCrawler {
52 52
   }
53 53
 
54 54
   _applyStaticOptions(node) {
55
-    const clazz = this.store.getOriginalComponentClassForName(node.data.name) || {};
55
+    const clazz = this.store.getComponentClassForName(node.data.name) ? this.store.getComponentClassForName(node.data.name)() : {};
56 56
     const staticOptions = _.isFunction(clazz.options) ? clazz.options(node.data.passProps || {}) : (_.cloneDeep(clazz.options) || {});
57 57
     const passedOptions = node.data.options || {};
58 58
     node.data.options = _.merge({}, staticOptions, passedOptions);

+ 30
- 12
lib/src/components/ComponentRegistry.test.tsx View File

@@ -8,8 +8,10 @@ describe('ComponentRegistry', () => {
8 8
   let uut;
9 9
   let store;
10 10
   let mockRegistry: any;
11
+  let mockWrapper: any;
11 12
 
12
-  class MyComponent extends React.Component {
13
+
14
+  class WrappedComponent extends React.Component {
13 15
     render() {
14 16
       return (
15 17
         <Text>
@@ -23,30 +25,46 @@ describe('ComponentRegistry', () => {
23 25
   beforeEach(() => {
24 26
     store = new Store();
25 27
     mockRegistry = AppRegistry.registerComponent = jest.fn(AppRegistry.registerComponent);
26
-    uut = new ComponentRegistry(store, {} as any);
28
+    mockWrapper = jest.mock('./ComponentWrapper');
29
+    mockWrapper.wrap = () => WrappedComponent;
30
+    uut = new ComponentRegistry(store, {} as any, mockWrapper);
27 31
   });
28 32
 
29
-  it('registers component component by componentName into AppRegistry', () => {
33
+  it('registers component by componentName into AppRegistry', () => {
30 34
     expect(mockRegistry).not.toHaveBeenCalled();
31
-    const result = uut.registerComponent('example.MyComponent.name', () => MyComponent);
35
+    const result = uut.registerComponent('example.MyComponent.name', () => {});
32 36
     expect(mockRegistry).toHaveBeenCalledTimes(1);
33 37
     expect(mockRegistry.mock.calls[0][0]).toEqual('example.MyComponent.name');
34
-    expect(mockRegistry.mock.calls[0][1]()).toEqual(result);
38
+    expect(mockRegistry.mock.calls[0][1]()).toEqual(result());
35 39
   });
36 40
 
37
-  it('saves the original component into the store', () => {
38
-    expect(store.getOriginalComponentClassForName('example.MyComponent.name')).toBeUndefined();
39
-    uut.registerComponent('example.MyComponent.name', () => MyComponent);
40
-    const Class = store.getOriginalComponentClassForName('example.MyComponent.name');
41
+  it('saves the wrapper component generator the store', () => {
42
+    expect(store.getComponentClassForName('example.MyComponent.name')).toBeUndefined();
43
+    uut.registerComponent('example.MyComponent.name', () => {});
44
+    const Class = store.getComponentClassForName('example.MyComponent.name');
41 45
     expect(Class).not.toBeUndefined();
42
-    expect(Class).toEqual(MyComponent);
43
-    expect(Object.getPrototypeOf(Class)).toEqual(React.Component);
46
+    expect(Class()).toEqual(WrappedComponent);
47
+    expect(Object.getPrototypeOf(Class())).toEqual(React.Component);
44 48
   });
45 49
 
46 50
   it('resulting in a normal component', () => {
47
-    uut.registerComponent('example.MyComponent.name', () => MyComponent);
51
+    uut.registerComponent('example.MyComponent.name', () => {});
48 52
     const Component = mockRegistry.mock.calls[0][1]();
49 53
     const tree = renderer.create(<Component componentId='123' />);
50 54
     expect(tree.toJSON()!.children).toEqual(['Hello, World!']);
51 55
   });
56
+
57
+  it('should not invoke generator', () => {
58
+    const generator = jest.fn(() => {});
59
+    uut.registerComponent('example.MyComponent.name', generator);
60
+    expect(generator).toHaveBeenCalledTimes(0);
61
+  });
62
+
63
+  it('saves wrapped component to store', () => {
64
+    jest.spyOn(store, 'setComponentClassForName');
65
+    const generator = jest.fn(() => {});
66
+    const componentName = 'example.MyComponent.name';
67
+    uut.registerComponent(componentName, generator);
68
+    expect(store.getComponentClassForName(componentName)()).toEqual(WrappedComponent);
69
+  });
52 70
 });

+ 7
- 7
lib/src/components/ComponentRegistry.ts View File

@@ -1,17 +1,17 @@
1 1
 import { AppRegistry, ComponentProvider } from 'react-native';
2 2
 import { ComponentWrapper } from './ComponentWrapper';
3
-import { ComponentType } from 'react';
4 3
 import { Store } from './Store';
5 4
 import { ComponentEventsObserver } from '../events/ComponentEventsObserver';
6 5
 
7 6
 export class ComponentRegistry {
8
-  constructor(private readonly store: Store, private readonly componentEventsObserver: ComponentEventsObserver) { }
7
+  constructor(private readonly store: Store, private readonly componentEventsObserver: ComponentEventsObserver, private readonly ComponentWrapperClass: typeof ComponentWrapper) { }
9 8
 
10
-  registerComponent(componentName: string, getComponentClassFunc: ComponentProvider, ReduxProvider?: any, reduxStore?: any): ComponentType<any> {
11
-    const OriginalComponentClass = getComponentClassFunc();
12
-    const NavigationComponent = ComponentWrapper.wrap(componentName, OriginalComponentClass, this.store, this.componentEventsObserver, ReduxProvider, reduxStore);
13
-    this.store.setOriginalComponentClassForName(componentName, OriginalComponentClass);
14
-    AppRegistry.registerComponent(componentName, () => NavigationComponent);
9
+  registerComponent(componentName: string, getComponentClassFunc: ComponentProvider, ReduxProvider?: any, reduxStore?: any): ComponentProvider {
10
+    const NavigationComponent = () => {
11
+      return this.ComponentWrapperClass.wrap(componentName, getComponentClassFunc, this.store, this.componentEventsObserver, ReduxProvider, reduxStore)
12
+    };
13
+    this.store.setComponentClassForName(componentName, NavigationComponent);
14
+    AppRegistry.registerComponent(componentName, NavigationComponent);
15 15
     return NavigationComponent;
16 16
   }
17 17
 }

+ 13
- 13
lib/src/components/ComponentWrapper.test.tsx View File

@@ -53,7 +53,7 @@ describe('ComponentWrapper', () => {
53 53
   });
54 54
 
55 55
   it('must have componentId as prop', () => {
56
-    const NavigationComponent = ComponentWrapper.wrap(componentName, MyComponent, store, componentEventsObserver);
56
+    const NavigationComponent = ComponentWrapper.wrap(componentName, () => MyComponent, store, componentEventsObserver);
57 57
     const orig = console.error;
58 58
     console.error = (a) => a;
59 59
     expect(() => {
@@ -63,7 +63,7 @@ describe('ComponentWrapper', () => {
63 63
   });
64 64
 
65 65
   it('wraps the component', () => {
66
-    const NavigationComponent = ComponentWrapper.wrap(componentName, MyComponent, store, componentEventsObserver);
66
+    const NavigationComponent = ComponentWrapper.wrap(componentName, () => MyComponent, store, componentEventsObserver);
67 67
     expect(NavigationComponent).not.toBeInstanceOf(MyComponent);
68 68
     const tree = renderer.create(<NavigationComponent componentId={'component1'} />);
69 69
     expect(tree.toJSON()!.children).toEqual(['Hello, World!']);
@@ -71,14 +71,14 @@ describe('ComponentWrapper', () => {
71 71
 
72 72
   it('injects props from wrapper into original component', () => {
73 73
     const renderCount = jest.fn();
74
-    const NavigationComponent = ComponentWrapper.wrap(componentName, MyComponent, store, componentEventsObserver);
74
+    const NavigationComponent = ComponentWrapper.wrap(componentName, () => MyComponent, store, componentEventsObserver);
75 75
     const tree = renderer.create(<NavigationComponent componentId={'component1'} text={'yo'} renderCount={renderCount} />);
76 76
     expect(tree.toJSON()!.children).toEqual(['yo']);
77 77
     expect(renderCount).toHaveBeenCalledTimes(1);
78 78
   });
79 79
 
80 80
   it('updates props from wrapper into original component on state change', () => {
81
-    const NavigationComponent = ComponentWrapper.wrap(componentName, MyComponent, store, componentEventsObserver);
81
+    const NavigationComponent = ComponentWrapper.wrap(componentName, () => MyComponent, store, componentEventsObserver);
82 82
     const tree = renderer.create(<TestParent ChildClass={NavigationComponent} />);
83 83
     expect(myComponentProps.foo).toEqual(undefined);
84 84
     (tree.getInstance() as any).setState({ propsFromState: { foo: 'yo' } });
@@ -87,13 +87,13 @@ describe('ComponentWrapper', () => {
87 87
 
88 88
   it('pulls props from the store and injects them into the inner component', () => {
89 89
     store.setPropsForId('component123', { numberProp: 1, stringProp: 'hello', objectProp: { a: 2 } });
90
-    const NavigationComponent = ComponentWrapper.wrap(componentName, MyComponent, store, componentEventsObserver);
90
+    const NavigationComponent = ComponentWrapper.wrap(componentName, () => MyComponent, store, componentEventsObserver);
91 91
     renderer.create(<NavigationComponent componentId={'component123'} />);
92 92
     expect(myComponentProps).toEqual({ componentId: 'component123', numberProp: 1, stringProp: 'hello', objectProp: { a: 2 } });
93 93
   });
94 94
 
95 95
   it('updates props from store into inner component', () => {
96
-    const NavigationComponent = ComponentWrapper.wrap(componentName, MyComponent, store, componentEventsObserver);
96
+    const NavigationComponent = ComponentWrapper.wrap(componentName, () => MyComponent, store, componentEventsObserver);
97 97
     const tree = renderer.create(<TestParent ChildClass={NavigationComponent} />);
98 98
     store.setPropsForId('component1', { myProp: 'hello' });
99 99
     expect(myComponentProps.foo).toEqual(undefined);
@@ -104,7 +104,7 @@ describe('ComponentWrapper', () => {
104 104
   });
105 105
 
106 106
   it('protects id from change', () => {
107
-    const NavigationComponent = ComponentWrapper.wrap(componentName, MyComponent, store, componentEventsObserver);
107
+    const NavigationComponent = ComponentWrapper.wrap(componentName, () => MyComponent, store, componentEventsObserver);
108 108
     const tree = renderer.create(<TestParent ChildClass={NavigationComponent} />);
109 109
     expect(myComponentProps.componentId).toEqual('component1');
110 110
     (tree.getInstance() as any).setState({ propsFromState: { id: 'ERROR' } });
@@ -112,7 +112,7 @@ describe('ComponentWrapper', () => {
112 112
   });
113 113
 
114 114
   it('assignes key by id', () => {
115
-    const NavigationComponent = ComponentWrapper.wrap(componentName, MyComponent, store, componentEventsObserver);
115
+    const NavigationComponent = ComponentWrapper.wrap(componentName, () => MyComponent, store, componentEventsObserver);
116 116
     const tree = renderer.create(<NavigationComponent componentId={'component1'} />);
117 117
     expect(myComponentProps.componentId).toEqual('component1');
118 118
     expect((tree.getInstance() as any)._reactInternalInstance.child.key).toEqual('component1');
@@ -120,20 +120,20 @@ describe('ComponentWrapper', () => {
120 120
 
121 121
   it('cleans props from store on unMount', () => {
122 122
     store.setPropsForId('component123', { foo: 'bar' });
123
-    const NavigationComponent = ComponentWrapper.wrap(componentName, MyComponent, store, componentEventsObserver);
123
+    const NavigationComponent = ComponentWrapper.wrap(componentName, () => MyComponent, store, componentEventsObserver);
124 124
     const tree = renderer.create(<NavigationComponent componentId={'component123'} />);
125 125
     expect(store.getPropsForId('component123')).toEqual({ foo: 'bar' });
126 126
     tree.unmount();
127 127
     expect(store.getPropsForId('component123')).toEqual({});
128 128
   });
129 129
 
130
-  it(`merges static members from wrapped component`, () => {
131
-    const NavigationComponent = ComponentWrapper.wrap(componentName, MyComponent, store, componentEventsObserver) as any;
130
+  it(`merges static members from wrapped component when generated`, () => {
131
+    const NavigationComponent = ComponentWrapper.wrap(componentName, () => MyComponent, store, componentEventsObserver) as any;
132 132
     expect(NavigationComponent.options).toEqual({ title: 'MyComponentTitle' });
133 133
   });
134 134
 
135 135
   it(`calls unmounted on componentEventsObserver`, () => {
136
-    const NavigationComponent = ComponentWrapper.wrap(componentName, MyComponent, store, componentEventsObserver);
136
+    const NavigationComponent = ComponentWrapper.wrap(componentName, () => MyComponent, store, componentEventsObserver);
137 137
     const tree = renderer.create(<NavigationComponent componentId={'component123'} />);
138 138
     verify(mockedComponentEventsObserver.unmounted('component123')).never();
139 139
     tree.unmount();
@@ -162,7 +162,7 @@ describe('ComponentWrapper', () => {
162 162
     const reduxStore = require('redux').createStore((state = initialState) => state);
163 163
 
164 164
     it(`wraps the component with a react-redux provider with passed store`, () => {
165
-      const NavigationComponent = ComponentWrapper.wrap(componentName, ConnectedComp, store, componentEventsObserver, ReduxProvider, reduxStore);
165
+      const NavigationComponent = ComponentWrapper.wrap(componentName, () => ConnectedComp, store, componentEventsObserver, ReduxProvider, reduxStore);
166 166
       const tree = renderer.create(<NavigationComponent componentId={'theCompId'} />);
167 167
       expect(tree.toJSON()!.children).toEqual(['it just works']);
168 168
       expect((NavigationComponent as any).options).toEqual({ foo: 123 });

+ 5
- 3
lib/src/components/ComponentWrapper.tsx View File

@@ -1,4 +1,5 @@
1 1
 import * as React from 'react';
2
+import { ComponentProvider } from 'react-native';
2 3
 import * as  _ from 'lodash';
3 4
 import * as ReactLifecyclesCompat from 'react-lifecycles-compat';
4 5
 import { Store } from './Store';
@@ -10,12 +11,13 @@ interface HocProps { componentId: string; }
10 11
 export class ComponentWrapper {
11 12
   static wrap(
12 13
     componentName: string,
13
-    OriginalComponentClass: React.ComponentType<any>,
14
+    OriginalComponentGenerator: ComponentProvider,
14 15
     store: Store,
15 16
     componentEventsObserver: ComponentEventsObserver,
16 17
     ReduxProvider?: any,
17 18
     reduxStore?: any
18 19
   ): React.ComponentClass<any> {
20
+    const GeneratedComponentClass = OriginalComponentGenerator();
19 21
     class WrappedComponent extends React.Component<HocProps, HocState> {
20 22
       static getDerivedStateFromProps(nextProps: any, prevState: HocState) {
21 23
         return {
@@ -39,7 +41,7 @@ export class ComponentWrapper {
39 41
 
40 42
       render() {
41 43
         return (
42
-          <OriginalComponentClass
44
+          <GeneratedComponentClass
43 45
             {...this.state.allProps}
44 46
             componentId={this.state.componentId}
45 47
             key={this.state.componentId}
@@ -55,7 +57,7 @@ export class ComponentWrapper {
55 57
     }
56 58
 
57 59
     ReactLifecyclesCompat.polyfill(WrappedComponent);
58
-    require('hoist-non-react-statics')(WrappedComponent, OriginalComponentClass);
60
+    require('hoist-non-react-statics')(WrappedComponent, GeneratedComponentClass);
59 61
 
60 62
     if (reduxStore && ReduxProvider) {
61 63
       return ComponentWrapper.wrapWithRedux(WrappedComponent, ReduxProvider, reduxStore);

+ 2
- 2
lib/src/components/Store.test.ts View File

@@ -26,8 +26,8 @@ describe('Store', () => {
26 26
     const MyComponent = class {
27 27
       //
28 28
     };
29
-    uut.setOriginalComponentClassForName('example.mycomponent', MyComponent);
30
-    expect(uut.getOriginalComponentClassForName('example.mycomponent')).toEqual(MyComponent);
29
+    uut.setComponentClassForName('example.mycomponent', MyComponent);
30
+    expect(uut.getComponentClassForName('example.mycomponent')).toEqual(MyComponent);
31 31
   });
32 32
 
33 33
   it('clean by component id', () => {

+ 3
- 3
lib/src/components/Store.ts View File

@@ -12,14 +12,14 @@ export class Store {
12 12
     return _.get(this.propsById, componentId, {});
13 13
   }
14 14
 
15
-  setOriginalComponentClassForName(componentName: string, ComponentClass) {
15
+  setComponentClassForName(componentName: string, ComponentClass) {
16 16
     _.set(this.componentsByName, componentName, ComponentClass);
17 17
   }
18 18
 
19
-  getOriginalComponentClassForName(componentName: string) {
19
+  getComponentClassForName(componentName: string) {
20 20
     return _.get(this.componentsByName, componentName);
21 21
   }
22
-
22
+  
23 23
   cleanId(id: string) {
24 24
     _.unset(this.propsById, id);
25 25
   }